代码随想录第28天 | 93.复原IP地址 、 78.子集 、 90.子集II

一、前言:

参考文献:代码随想录

今天的主题内容是回溯算法,这一章的干货很多,我需要慢慢的品味,不单单只是表象,还需要研究深层原理。

二、复原IP地址

1、思路:

(1)首先还是确定返回值和参数:

void backtracking(string &s, int startIndex, int pointSum)

这里比往常多了一个pointSum,这个是来判断是否符合ip格式的一个标志,也就是记录这个s中存在多少个".";

(2)终止条件如下:

// pointsum是用来判断这个字符串中存在多少个"."如果有了三个,就说明满足IP格式了if (pointSum == 3) {if (isValud(s, startIndex, s.size() - 1)) {// 这里还有一个条件就是判断最后的一段是否符合IP要求result.push_back(s);}return;} 

这里首先要判断是否有三个”.“,存在之后,再判断最后的那一段是否符合IP的格式,然后才能插入,如果不符合那就直接return回溯了。

(3)单层递归逻辑:

for (int i = startIndex; i < s.size(); i++) {if (isValud(s, startIndex, i)) {s.insert(s.begin() + i + 1, '.'); // 插入"."pointSum++;backtracking(s, i + 2, pointSum); // 这里是 i+2 此逻辑是因为加了"."需要多加一个1// 回溯pointSum--;s.erase(s.begin() + i + 1); // 删除"."} else {break;}}

看起来并不复杂,但是,难疑点比较多。首先就是先判断当前的这个切片处是否符合IP格式,然后再进行插入逗点,pointSum再做记录,然后就可以开始递归了,这里的是 i+2的,因为这个时候插入了逗点,所以需要后移一位,接着就是回溯了。

(4)主函数中存在一个小小的剪枝操作,如下:

if (s.size() < 4 || s.size() > 12) return result;

(5)判断是否为ip的函数为:

    bool isValud(string &s, int start, int end) {if (start > end) {return false;}// 头号字符不能为0(只有一位时可以)if (s[start] == '0' && start != end) {return false;}// 小于等于255int num = 0;for (int i = start; i <= end; i++) {// 不为合法数字也排除if (s[i] > '9' || s[i] < '0') {return false;}num = num * 10 + (s[i] - '0');if (num > 255) {return false;}}return true;}

这里的细节也比多:

1、start和end的比较;

2、头数字不为0,且不是只有一个数字;

3、和小于等于255;

2、整体代码如下:

class Solution {
private:// 判断是否为合法IPbool isValud(string &s, int start, int end) {if (start > end) {return false;}// 头号字符不能为0(只有一位时可以)if (s[start] == '0' && start != end) {return false;}// 小于等于255int num = 0;for (int i = start; i <= end; i++) {// 不为合法数字也排除if (s[i] > '9' || s[i] < '0') {return false;}num = num * 10 + (s[i] - '0');if (num > 255) {return false;}}return true;}vector<string> result;void backtracking(string &s, int startIndex, int pointSum) { // pointsum是用来判断这个字符串中存在多少个"."如果有了三个,就说明满足IP格式了if (pointSum == 3) {if (isValud(s, startIndex, s.size() - 1)) {// 这里还有一个条件就是判断最后的一段是否符合IP要求result.push_back(s);}return;} // 单层递归逻辑for (int i = startIndex; i < s.size(); i++) {if (isValud(s, startIndex, i)) {s.insert(s.begin() + i + 1, '.'); // 插入"."pointSum++;backtracking(s, i + 2, pointSum); // 这里是 i+2 此逻辑是因为加了"."需要多加一个1// 回溯pointSum--;s.erase(s.begin() + i + 1); // 删除"."} else {break;}}}
public:vector<string> restoreIpAddresses(string s) {if (s.size() < 4 || s.size() > 12) return result; // 算是剪枝了backtracking(s, 0 , 0);return result;}
};

 三、子集

1、思路:

(1)返回值和终止条件并没有什么改变:

void backtracking(vector<int> &nums, startIndex)

(2)终止条件(这个条件可有可不有,因为在return时以及到了叶子节点处,循环自然就不去了,就不用手动终止了):

if (startIndex >= nums.size()) return;

(3)单层递归逻辑:

for (int i = startIndex; i < nums.size(); i++) {// 插入元素path.push_back(nums[i]);// 递归backtracking(nums, i + 1);// 回溯path.pop_back();}

还是插入,递归,回溯。。。

(4)最重要的就是收集path,在每次递归开始时就可以收集子集了;

2、整体代码如下:

class Solution {
private:vector<int> path;vector<vector<int>> result;void backtracking(vector<int>& nums, int startIndex) {// 收集结果,每递归一次就可以收集一次结果result.push_back(path);// 终止条件,可写可不写,因为到了最后的叶子节点,自然会终止的if (startIndex >= nums.size()) return;for (int i = startIndex; i < nums.size(); i++) {// 插入元素path.push_back(nums[i]);// 递归backtracking(nums, i + 1);// 回溯path.pop_back();}return;}
public:vector<vector<int>> subsets(vector<int>& nums) {backtracking(nums, 0);return result;}
};

 四、子集||

1、思路:

这个题目和上一题加上组合总和|||综合,这里也需要添加一个used来判断是否使用了这个元素,如果使用了那就可以继续遍历,说明在树枝上,但是如前面一个元素相同,但是没有被使用,说明在数层上面,就需要跳过这个数字了,避免重复。

图解如下:

 

 

这里就不一步步分析了;

2、整体代码如下:

class Solution {
private:vector<int> path;vector<vector<int>> result;void backtracking(vector<int>& nums, int startIndex, vector<bool> &used) {result.push_back(path);for (int i = startIndex; i < nums.size(); i++) {if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) {continue;}path.push_back(nums[i]);used[i] = true;backtracking(nums, i + 1, used);used[i] = false;path.pop_back();}return;}
public:vector<vector<int>> subsetsWithDup(vector<int>& nums) {vector<bool> used(nums.size(), false);sort(nums.begin(), nums.end());backtracking(nums, 0, used);return result;}
};

今日学习时间:2小时

leave message:

Her behavior is well-accorded with the expectations of her parents.

她的行为与父母的期望相符。 

 

 

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

通义灵码智能编程助手

通义灵码是阿里云出品的一款基于通义大模型的智能编码辅助工具&#xff0c;提供行级/函数级实时续写、自然语言生成代码、单元测试生成、代码注释生成、代码解释、研发智能问答、异常报错排查等能力&#xff0c;并针对阿里云 SDK/OpenAPI 的使用场景调优&#xff0c;助力开发者…

Git命令(1)[删除,恢复与移动]

文章目录 1.删除文件1.1命令----rm <filename>1.2命令----git rm <filename>1.1命令----git rm <filename> -f 2.恢复文件2.1命令----git restore <filename>2.1命令----git restore --staged <filename> 3.重命名文件3.1命令----mv <oldFile…

网络编程详解(select poll epoll reactor)

1. 客户端服务器建立连接过程 1.1 编写一个server的步骤是怎么样的&#xff1f; int main(){int listenfd, connfd;pid_t childpid;socklen_t clilen;struct sockaddr_in cliaddr, servaddr;listenfd socket(AF_INET, SOCK_STREAM, 0);bzero(&servaddr, sizeof(servaddr…

12313124

c语言中的小小白-CSDN博客c语言中的小小白关注算法,c,c语言,贪心算法,链表,mysql,动态规划,后端,线性回归,数据结构,排序算法领域.https://blog.csdn.net/bhbcdxb123?spm1001.2014.3001.5343 给大家分享一句我很喜欢我话&#xff1a; 知不足而奋进&#xff0c;望远山而前行&am…

中科驭数超低时延网络解决方案入选2023年度金融信创优秀解决方案

近日&#xff0c;由中国人民银行领导、中国金融电子化集团有限公司牵头组建的金融信创生态实验室发布「2023年度第三期金融信创优秀解决方案」&#xff0c;中科驭数超低时延网络解决方案从众多方案中脱颖而出&#xff0c;成功入选&#xff0c;代表了该方案的技术创新和金融实践…

【Python系列】数据遍历

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

糖尿病新世界杂志糖尿病新世界杂志社糖尿病新世界编辑部2023年第24期目录

论著 苦参汤加味坐浴熏洗联合胰岛素对糖尿病患者患炎性外痔的临床疗效探讨 孙孝仁;林星鹏;李密; 1-4 《糖尿病新世界》投稿&#xff1a;yixuebj126.com 尿蛋白、尿微量蛋白指标联合检测在糖尿病患者早期肾损伤中的诊断价值 郑艳斌;卢永芳;徐小华;王跃华; 5-8 血清…

【MySQL系列】使用 ALTER TABLE 语句修改表结构的方法

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

SVM简介 详细推导 核函数 线性可分 非线性可分

注意&#xff1a;由于该文章由jupyter nbconvert导出&#xff0c;若单独执行代码可能出现变量找不到或者没有导入库的情况&#xff0c;正确的做法是将所有的代码片段按顺序放到一个.py文件里面或者按顺序放入一个.ipynb文件的多个代码块中。 SVM(Support Vector Machine) Vap…

yolov5关键点检测-实现溺水检测与警报提示(代码+原理)

基于YOLOv5的关键点检测应用于溺水检测与警报提示是一种结合深度学习与计算机视觉技术的安全监控解决方案。该项目通常会利用YOLOv5强大的实时目标检测能力&#xff0c;并通过扩展或修改网络结构以支持人体关键点检测&#xff0c;来识别游泳池或其他水域中人们的行为姿态。 项…

程序员找不到接单平台?看这篇,全搞定!赶紧收藏!

天空一声巨响&#xff0c;程序员闪亮登场&#xff0c;早九晚五996&#xff0c;一看工资886&#xff01;心寒&#xff01;真正的心寒&#xff01;咱程序员看似风光无限好&#xff0c;只不过只有咱局中人才知道现在工资有多少&#xff0c;养家糊口真的很难诶&#xff01; 但是嘛&…

整型之韵,数之舞:大小端与浮点数的内存之旅

✨✨欢迎&#x1f44d;&#x1f44d;点赞☕️☕️收藏✍✍评论 个人主页&#xff1a;秋邱’博客 所属栏目&#xff1a;人工智能 &#xff08;感谢您的光临&#xff0c;您的光临蓬荜生辉&#xff09; 1.0 整形提升 我们先来看看代码。 int main() {char a 3;char b 127;char …