Studying-代码随想录训练营day24| 93.复原IP地址、78.子集、90.子集II

第24天,回溯算法part03,牢记回溯三部曲,掌握树形结构结题方法💪

目录

93.复原IP地址

78.子集

90.子集II

总结 


93.复原IP地址

文档讲解:代码随想录复原IP地址

视频讲解:手撕复原IP地址

题目:

学习:本题属于切割类问题,不同的是本题需要使用 ' · ’ 来切割,并且本题对切割的数字大小和多少,切割多少次都有要求。但本质都是两步:1.切割;2.判断切割是否正确。

依据以上两点,本题和131.分割回文串不同的地方就在于对分割部分的判断和终止条件的选择。回溯逻辑用树形结构来表示为:

注意:判断分割部分是否合法,主要从三个部分出发:1.段位以0为开头且不止有0的数字不合法。2.段位里有非正整数字符不合法。3.段位如果大于255了不合法。

代码:确定回溯三部曲,注意本题要在字符串中加入' . ' 因此回溯的时候要删掉该点。

//时间复杂度O(3^4)
//空间复杂度O(n)
class Solution {
public:
    //直接在字符串上进行操作,因此不设置路径数组
    vector<string> result; //返回数组
    //确定返回值和参数列表,直接在答案数组中插入因此不需要返回值,参数中需要原字符串s,分割点startindex
    //本题还需要一个int型变量point表示当前逗号的数量
    void backtracking(string& s, int startindex, int point) {
        //确定终止条件,当逗号数量为3个时,说明当前分割已经完成了
        if(point == 3) {
            //最后一部分字符串还需要进行判断
            if(ipvaild(s, startindex, s.size() - 1)) {
                result.push_back(s);
            }
            return;
        }

        //确定单层递归逻辑
        for(int i = startindex; i < s.size(); i++) {
            //startindex作为切割线,切割的字符串区间为[startindex, i],左闭右闭
            //判断切割下来的字符串是否合理
            if(ipvaild(s, startindex, i)){
                //如果合理的话,在字符串下标i后插入逗号,并进行下一轮递归
                s.insert(s.begin() + i + 1, '.');
                point++;
                //注意这里需要传入的是i+2,因为加了一个逗号,切割的位置需要往后移两位
                backtracking(s, i + 2, point);
                point--; //回溯
                s.erase(s.begin() + i + 1);
            }
            else {  //假如不满足,后续的切割方法也难以满足,直接跳出本层循环
                break;
            }
        }
    }
    bool ipvaild(string& s, int start, int end) {
        if (start > end) {
            return false;
        }
        //如果存在前置0的话,返回false
        if(start != end && s[start] == '0') {
            return false;
        }
        int num = 0; //对切割字符串进行求和
        for(int i = start; i <= end; i++) {
            if(s[i] - '0' < 0 || s[i] - '0' > 9) {
                return false;
            }
            num = num * 10 + (s[i] - '0');
            if(num > 255) {
                return false;
            }
        }
        return true;
    }
    vector<string> restoreIpAddresses(string s) {
        backtracking(s, 0, 0);
        return result;
    }
};

本题可以进行剪枝,自认为本题可以从三个部分进行剪枝,分别是:1.剪枝1,给的字符串不满足切割有效的IP地址;2.剪枝2,分割实际只需要分割3个字符就行,缩小循环范围;3.每次切割后可以判断一下是否后面的字符还能够满足切割要求。

代码:

class Solution {
public:
    //切割问题主要需要两点:切割,判断!
    //直接在字符串上进行操作,因此不设置路径数组
    vector<string> result; //返回数组
    //确定返回值和参数列表,直接在答案数组中插入因此不需要返回值,参数中需要原字符串s,分割点startindex
    //本题还需要一个int型变量point表示当前逗号的数量
    void backtracking(string& s, int startindex, int point) {
        //确定终止条件,当逗号数量为3个时,说明当前分割已经完成了
        if(point == 3) {
            //最后一部分字符串还需要进行判断
            if(ipvaild(s, startindex, s.size() - 1)) {
                result.push_back(s);
            }
            return;
        }

        //确定单层递归逻辑
        //剪枝2,分割只需要分割3个数字就够了
        for(int i = startindex; i < startindex + 3; i++) {
            //剪枝3,后续剩余的节点数不满足切割要求
            if(s.size() - startindex > (4 - point) * 3 || s.size() - startindex < (4 - point)) {
                break;
            }
            //startindex作为切割线,切割的字符串区间为[startindex, i],左闭右闭
            //判断切割下来的字符串是否合理
            if(ipvaild(s, startindex, i)){
                //如果合理的话,在字符串下标i后插入逗号,并进行下一轮递归
                s.insert(s.begin() + i + 1, '.');
                point++;
                //注意这里需要传入的是i+2,因为加了一个逗号,切割的位置需要往后移两位
                backtracking(s, i + 2, point);
                point--; //回溯
                s.erase(s.begin() + i + 1);
            }
            else {  //假如不满足,后续的切割方法也难以满足,直接跳出本层循环
                break;
            }
        }
    }
    bool ipvaild(string& s, int start, int end) {
        if (start > end) {
            return false;
        }
        //如果存在前置0的话,返回false
        if(start != end && s[start] == '0') {
            return false;
        }
        int num = 0; //对切割字符串进行求和
        for(int i = start; i <= end; i++) {
            if(s[i] - '0' < 0 || s[i] - '0' > 9) {
                return false;
            }
            num = num * 10 + (s[i] - '0');
            if(num > 255) {
                return false;
            }
        }
        return true;
    }
    vector<string> restoreIpAddresses(string s) {
        //剪枝1,给的字符串不满足切割有效的ip地址
        if(s.size() < 4 || s.size() > 12) return result;
        backtracking(s, 0, 0);
        return result;
    }
};

78.子集

文档讲解:代码随想录子集

视频讲解:手撕子集问题

题目:

学习:回溯算法能够解决的第三类问题,子集问题。子集问题与切割问题和组合问题的本质不同在于,切割问题和组合问题都是在叶子节点收获结果,但是子集问题需要在每个节点都收获结果,这也导致了子集问题对result数组push_back的位置不同,但其他部分其实几乎是一致的。子集问题其实也能看作是一个组合问题,因此也需要注意去重。回溯逻辑转化为树形结构为:

代码:确定回溯三部曲

//时间复杂度O(n*2^n)
//空间复杂度O(n)
class Solution {
public:
    vector<vector<int>> result; //返回数组
    vector<int> path; //保存路径
    //确定返回值和参数列表,在数组中直接进行操作,所以不需要返回值,参数列表需要遍历的数组和当前遍历的下标
    void backtracking(vector<int>& nums, int startindex) {
        //子集问题的不同在于,子集收获答案是在每个节点均收货一次
        //在终止条件前,先进行收获,其中也包含了空集
        result.push_back(path);
        //确定终止条件(其实等于就可以了),遍历到最后
        //该终止条件也可以不写,因为当startindex >= nums.size()时,下面的for循环也不会进入,但要注意for循环后加return。
        if(startindex >= nums.size()) {
            return;
        }

        //确定单层递归逻辑
        for(int i = startindex; i < nums.size(); i++) {
            path.push_back(nums[i]);
            //传入i+1,防止出现重复
            backtracking(nums, i + 1);
            path.pop_back();
        }
        return;
    }
    vector<vector<int>> subsets(vector<int>& nums) {
        backtracking(nums, 0);
        return result;
    }
};

90.子集II

文档讲解:代码随想录子集II

视频讲解:手撕子集II

题目:

学习:本题和上一题不同点在于本题存在重复元素,需要对后续的相同元素进行去重,事实上本题和组合总和II的去重是相同的,本质都是如果后面出现了与前面相同的元素就可以跳过该元素的遍历,因为前面的元素一定把后面的元素还有的组合都包括的。基于此本题可以采取和40.组合总和II相同的去重方式,都是在树层进行去重

代码:确定回溯三部曲

//时间复杂度O(n*2^n)
//空间复杂度O(n)
class Solution {
public:  
    vector<vector<int>> result; //返回答案数组
    vector<int> path; //保存路径
    //确定参数和返回值
    void backtracking(vector<int>& nums, int startindex) {
        //收集每一个节点
        result.push_back(path);
        //确定终止条件
        if(startindex == nums.size()) {
            return;
        }

        //确定单层递归逻辑
        for(int i = startindex; i < nums.size(); i++) {
            //去重
            if(i > startindex && nums[i] == nums[i-1]){
                continue;
            }
            path.push_back(nums[i]);
            backtracking(nums, i + 1);
            path.pop_back();
        }
        return;
    }
    vector<vector<int>> subsetsWithDup(vector<int>& nums) {
        //进行排序,便于去重
        sort(nums.begin(), nums.end());
        backtracking(nums, 0);
        return result;
    }
};

总结 

切割问题首尾,子集问题开始,牢记子集问题和切割问题和组合问题的不同。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/759693.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

python open函数中文乱码怎么解决

首先在D盘下新建一个html文档&#xff0c;接着在里面输入含有中文的Html字符&#xff0c;使用中文格式对读取的字符进行解码&#xff0c;再用utf-8的模式对字符进行编码&#xff0c;然后就能正确输出中文字符。 代码如下&#xff1a; # -*- coding: UTF-8 -*- file1 open(&quo…

策略模式在金融业务中的应用及其框架实现

引言 策略模式&#xff08;Strategy Pattern&#xff09;是一种行为设计模式&#xff0c;它允许在不修改客户端代码的情况下&#xff0c;动态地改变一个类的行为。它通过定义一系列算法并将它们封装在独立的策略类中&#xff0c;使这些算法可以互相替换&#xff0c;而不会影响…

【原理】机器学习中的最小二乘法公式推导过程

本文来自《老饼讲解-BP神经网络》https://www.bbbdata.com/ 目录 一、什么是最小二乘法1.1. 什么是最小二乘法1.2. 最小二乘法的求解公式 二、最小二乘法求解公式的推导 最小二乘法是基本的线性求解问题之一&#xff0c;本文介绍最小二乘法的原理&#xff0c;和最小二法求解公式…

Python技术笔记汇总(含语法、工具库、数科、爬虫等)

对Python学习方法及入门、语法、数据处理、数据可视化、空间地理信息、爬虫、自动化办公和数据科学的相关内容可以归纳如下&#xff1a; 一、Python学习方法 分解自己的学习目标&#xff1a;可以将学习目标分基础知识&#xff0c;进阶知识&#xff0c;高级应用&#xff0c;实…

开源模型破局OpenAI服务限制,15分钟灵活搭建RAG和Agent应用

简介&#xff1a; 今天&#xff0c;我们做了两个实验&#xff0c;目标在15分钟内&#xff0c;完成下载社区的开源模型&#xff0c;部署成API&#xff0c;替换LlamaIndex中RAG和LangChain中OpenAI接口Agent的最佳实践&#xff0c;并取得符合预期的结果。 实验一 实验目标&…

企业级im即时通讯,WorkPlus专注于政企移动数字化平台底座

企业级IM即时通讯是为满足政府和企业内部通讯需求而设计的高级通讯解决方案。作为一家专注于政企移动数字化平台底座的企业&#xff0c;WorkPlus为政府和企业提供了安全专属的移动数字化解决方案。本文将介绍企业级IM即时通讯的重要性、WorkPlus的特点和优势。 1. 企业级IM即时…

AttGAN实验复现 2024

AttnGAN 代码复现 2024 文章目录 AttnGAN 代码复现 2024简介环境python 依赖数据集TrainingPre-train DAMSMTrain AttnGAN SamplingB_VALIDATION 为 False (默认)B_VALIDATION 为 True 参考博客 简介 论文地址&#xff1a; https://arxiv.org/pdf/1711.10485.pdf 代码 python…

springboot使用测试类报空指针异常

检查了Service注解&#xff0c;还有Autowired注解&#xff0c;还有其他注解&#xff0c;后面放心没能解决问题&#xff0c;最后使用RunWith(SpringRunner.class)解决了问题&#xff01;&#xff01; 真的是✓8了&#xff0c;烦死了这个✓8报错&#xff01;

DIVE INTO DEEP LEARNING 56-60

文章目录 56 Gated Recurrent Unit(GRU)56.1 Motivation: How to focus on a sequence56.2 The concept of doors56.3 Candidate hidden state56.4 hidden state56.5 summarize56.6 QA 57 Long short-term memory network57.1 Basic concepts57.2 Long short-term memory netwo…

240630_昇思学习打卡-Day12-Transformer中的Multiple-Head Attention

240630_昇思学习打卡-Day12-Transformer中的Multiple-Head Attention 以下为观看大佬课程及查阅资料总结所得&#xff0c;附大佬视频链接&#xff1a;Transformer中Self-Attention以及Multi-Head Attention详解_哔哩哔哩_bilibili&#xff0c;强烈建议先去看大佬视频&#xff…

BGE M3-Embedding 模型介绍

BGE M3-Embedding来自BAAI和中国科学技术大学&#xff0c;是BAAI开源的模型。相关论文在https://arxiv.org/abs/2402.03216&#xff0c;论文提出了一种新的embedding模型&#xff0c;称为M3-Embedding&#xff0c;它在多语言性&#xff08;Multi-Linguality&#xff09;、多功能…

【MySQL】库的操作【创建和操纵】

文章目录 1.创建数据库1.1字符集和校验规则1.查看系统默认字符集以及校验规则2.查看数据库支持的字符集以及校验规则 1.2校验规则对数据库的影响1.创建一个数据库&#xff0c;校验规则使用utf8_ general_ ci[不区分大小写]2.创建一个数据库&#xff0c;校验规则使用utf8_ bin[区…

如何借助 LLM 设计和实现任务型对话 Agent

1 引言 在人工智能的快速发展中&#xff0c;任务型对话 Agent 正成为提升用户体验和工作效率的关键技术。这类系统通过自然语言交互&#xff0c;专注于高效执行特定任务&#xff0c;如预订酒店或查询天气。尽管市场上的开源框架如 Rasa 和 Microsoft Bot Framework 在对话理解…

24年诺瓦星云入职认知能力测验Verify + 职业性格问卷OPQ可搜索带解析求职SHL题库

一、走进西安诺瓦星云科技股份有限公司 西安诺瓦星云科技股份有限公司(简称诺瓦星云) 是全球极具竞争力的LED显示解决方案供应商&#xff0c;实施"基于西安&#xff0c;围绕北京与深圳&#xff0c;辐射全球"的全球化布局&#xff0c;总部位于西安&#xff0c;西安、…

嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间

目录 1 进程时间概念 2 times 函数 2.1 times 函数介绍 2.2 示例程序 3 clock 函数 3.1 clock 函数介绍 3.2 示例程序 1 进程时间概念 进程时间指的是进程从创建后&#xff08;也就是程序运行后&#xff09;到目前为止这段时间内使用 CPU 资源的时间总数&#xff0c;出…

足球虚拟越位线技术FIFA OT(一)

此系列文章用于记录和回顾开发越位线系统的过程&#xff0c;平时工作较忙&#xff0c;有空时更新。 越位线技术 越位技术已被用于图形化分析足球中潜在的越位情况。 自 2018 年将视频助理裁判 &#xff08;VAR&#xff09; 引入比赛规则以来&#xff0c;人们越来越关注准确确…

力扣 单词规律

所用数据结构 哈希表 核心方法 判断字符串pattern 和字符串s 是否存在一对一的映射关系&#xff0c;按照题意&#xff0c;双向连接的对应规律。 思路以及实现步骤 1.字符串s带有空格&#xff0c;因此需要转换成字符数组进行更方便的操作&#xff0c;将字符串s拆分成单词列表…

ESP32实现UDP连接——micropython版本

代码&#xff1a; import network import socket import timedef wifiInit(name, port):ap network.WLAN(network.AP_IF) # 创建一个热点ap.config(essidname, authmodenetwork.AUTH_OPEN) # 无需密码ap.active(True) # 激活热点ip ap.ifconfig()[0] # 获取ip地址print(…

C++(Python)肥皂泡沫普拉托边界膜曲面模型算法

&#x1f3af;要点 &#x1f3af;肥皂泡二维流体模拟 | &#x1f3af;泡沫普拉托边界膜曲面模型算法演化厚度变化 | &#x1f3af;螺旋曲面三周期最小结构生成 &#x1f4dc;皂膜用例&#xff1a;Python计算物理粒子及拉格朗日和哈密顿动力学 | Python和MATLAB粘性力接触力动…

WordPress中文网址导航栏主题风格模版HaoWa

模板介绍 WordPress响应式网站中文网址导航栏主题风格模版HaoWa1.3.1源码 HaoWA主题风格除行为主体导航栏目录外&#xff0c;对主题风格需要的小控制模块都开展了敞开式的HTML在线编辑器方式的作用配备&#xff0c;另外预埋出默认设置的编码构造&#xff0c;便捷大伙儿在目前…