当前位置: 首页 > news >正文

Day24| 93.复原IP地址、78.子集、90.子集II

93.复原IP地址

回溯三部曲

  • 递归参数

  • 需要startIndex记录递归开始位置、pointNum记录添加逗号的数量

  • 递归终止条件

  • 要求明确分成4段,所以pointNum==3时,终止递归

  • 终止后验证第四段是否合法,合法加入结果集

  • 单层搜索逻辑

  • 在循环中判断截取的子串是否合法,合法就加上.;不合法就结束本层循环

  • 递归调用时,下一层递归的startIndex要从i+2开始(因为需要在字符串中加入了分隔符.),同时记录分割符的数量pointNum 要 +1。

  • 回溯的时候,就将刚刚加入的分隔符. 删掉就可以了,pointNum也要-1。

判断子串是否合法

  • 段位以0为开头的数字不合法

  • 段位里有非正整数字符不合法

  • 段位如果大于255了不合法

public class Solution {public IList<string> res = new List<string>();public IList<string> RestoreIpAddresses(string s) {if(s.Length<4||s.Length>12) return res;Backtracking(s,0,0);return res;}public void Backtracking(string s,int startIndex,int pointNum){if(pointNum==3){if(isVaild(s,startIndex,s.Length-1)) res.Add(s);return;}for(int i=startIndex;i<s.Length;i++){if(isVaild(s,startIndex,i)){s=s.Insert(i+1,".");Backtracking(s,i+2,pointNum+1);s=s.Remove(i+1,1);}else break;}}private bool isVaild(string s,int start,int end){if(start>end) return false;if(s[start]=='0'&&start!=end) return false;int 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;}
}

78.子集

子集是收集树形结构中树的所有节点的结果

回溯三部曲

  • 递归函数参数

    • path是子集收集元素、res存放结果、startIndex表示开始位置

  • 递归终止条件

    • 剩余集合为空时,到达叶子节点

    • 换个角度想,不需要加终止条件,如果不满足,for循环会结束

  • 单层搜索逻辑

    • 不需要任何剪枝,需要遍历整棵树

public class Solution {public IList<IList<int>> res=new List<IList<int>>();public IList<int> path=new List<int>();public IList<IList<int>> Subsets(int[] nums) {BackTracking(nums,0);return res;}public void BackTracking(int[] nums,int startIndex){res.Add(new List<int>(path));if(startIndex>nums.Length) return;for(int i=startIndex;i<nums.Length;i++){path.Add(nums[i]);BackTracking(nums,i+1);path.RemoveAt(path.Count-1);}}
}

90.子集II

为了避免重复子集 —— 必须排序 + 去重

由于输入数组可能有重复元素,如 [1, 2, 2],我们可能会生成重复子集 [1,2][1,2]

为了解决这个问题:

🧹 步骤一:对数组排序

csharp
Array.Sort(nums);

🧹 步骤二:在同一层中跳过重复元素

在回溯的 for 循环中,加入如下判断:

csharp
if (i > startIndex && nums[i] == nums[i - 1]) continue;

含义:

  • i > startIndex:说明我们是同一层(平行节点);

  • nums[i] == nums[i - 1]:当前元素和前一个元素相同;

  • 所以跳过,避免重复选取开头是相同数字的路径

去重:

Level 0 (startIndex=0): for i from 0 to 2├── i=0 (nums[0]=1) → path=[1]│   └── Level 1 (startIndex=1): for i from 1 to 2│       ├── i=1 (nums[1]=2) → path=[1,2]│       │   └── Level 2 (startIndex=2): for i from 2 to 2│       │       └── i=2 (nums[2]=2) → path=[1,2,2]│       └── i=2 (nums[2]=2) ←❗️重复元素❗️│           ❗️nums[2] == nums[1] 且 i > startIndex → 跳过├── i=1 (nums[1]=2) → path=[2]│   └── Level 1 (startIndex=2): for i from 2 to 2│       └── i=2 (nums[2]=2) → path=[2,2]├── i=2 (nums[2]=2) ←❗️重复元素❗️❗️nums[2] == nums[1] 且 i > startIndex → 跳过
public class Solution {public IList<IList<int>> res=new List<IList<int>>();public IList<int> path=new List<int>();public IList<IList<int>> SubsetsWithDup(int[] nums) {Array.Sort(nums);BackTracking(nums,0);return res;}public void BackTracking(int[] nums,int startIndex){res.Add(new List<int>(path));for(int i=startIndex;i<nums.Length;i++){if(i>startIndex&&nums[i]==nums[i-1]) continue;path.Add(nums[i]);BackTracking(nums,i+1);path.RemoveAt(path.Count-1);}}
}

http://www.dtcms.com/a/286313.html

相关文章:

  • NIO简单介绍和运用
  • MySQL计数函数count原理分析
  • 深入理解Linux文件I/O:系统调用与标志位应用
  • 区块链加密技术全景解析
  • 高效VLP蛋白表达|病毒样颗粒生产|疫苗研发平台
  • 【无标题】标准模型粒子行为与11维拓扑量子色动力学模型严格对应的全面论述
  • 文献分享0719
  • MyBatis:配置文件完成增删改查_添加
  • 智慧后厨检测算法构建智能厨房防护网
  • 零基础入门:用按键精灵实现视频自动操作(附完整脚本)
  • C语言:数组
  • MySQL的关键日志
  • 洛谷 P1395 会议
  • Logback 配置的利器:深入理解<property>与<variable>
  • 教育行业网络升级最佳实践:SD-WAN、传统方案与混合方案对比分析
  • Android sdk 升级 34到35
  • SpringBoot中解决SpringApplication入口和其他Bean不在同属目录下的问题。
  • 暑期自学嵌入式——Day05补充(C语言阶段)
  • STM32+w5500+TcpClient学习笔记
  • 前端基础之《Vue(23)—跨域问题》
  • Effective Modern C++ 条款14:如果函数不抛出异常请使用noexcept
  • 如何将本地Git仓库推送到远程仓库的一个文件中并保留Commit记录
  • 对于编码电机-520直流减速电机
  • 硬核电子工程:从硅片到系统的全栈实战指南—— 融合电路理论、嵌入式开发与PCB设计的工程艺术
  • 正则表达式完全指南:从入门到实战
  • Web3加密货币交易:您需要知道的所有信息
  • 五分钟掌握 TDengine 数据文件的工作原理
  • 《设计模式之禅》笔记摘录 - 8.命令模式
  • 【Mediatek】AN7563搭建编译环境操作说明
  • 1 初识C++