算法打卡day24|回溯法篇04|Leetcode 93.复原IP地址、78.子集、90.子集II

算法题

Leetcode 93.复原IP地址

题目链接:93.复原IP地址

大佬视频讲解:复原IP地址视频讲解

 个人思路

这道题和昨天的分割回文串有点类似,但这里是限制了只能分割3次以及分割块的数字大小,根据这些不同的条件用回溯法解决就好啦

解法
回溯法

把切割问题抽象为如下树形结构

回溯法三部曲

1.递归参数

这里的startIndex一定是需要的,因为不能重复分割,记录下一层递归分割的起始位置。

还需要一个变量pointNum,记录添加逗点的数量。

2.递归终止条件

本题明确要求只会分成4段,所以不能用切割线切到最后作为终止条件,而是分割的段数作为终止条件pointNum表示逗点数量,pointNum为3说明字符串分成了4段了。然后验证一下第四段是否合法,如果合法就加入到结果集里

3.单层搜索的逻辑

for (int i = startIndex; i < s.size(); i++)循环中 [startIndex, i] 这个区间就是截取的子串,需要判断这个子串是否合法。如果合法就在字符串后面加上符号.表示已经分割。如果不合法就结束本层循环,如图中剪掉的分支:

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

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

判断子串是否合法

按题意看主要考虑到如下三点:

  • 段位以0为开头的数字不合法
  • 段位里有非正整数字符不合法
  • 段位如果大于255了不合法

class Solution {List<String> result = new ArrayList<String>();//结果列表StringBuilder stringBuilder = new StringBuilder();//收割子字符串public List<String> restoreIpAddresses(String s) {restoreIpAddressesHandler(s, 0, 0);return result;}public void restoreIpAddressesHandler(String s, int start, int number) {// number表示stringbuilder中ip段的数量// 如果start等于s的长度并且ip段的数量是4,则加入结果集,并返回if (start == s.length() && number == 4) {result.add(stringBuilder.toString());return;}// 如果start等于s的长度但是ip段的数量不为4,或者ip段的数量为4但是start小于s的长度,则直接返回if (start == s.length() || number == 4) {return;}// 剪枝:ip段的长度最大是3,并且ip段处于[0,255]for (int i = start; i < s.length() && i - start < 3 && Integer.parseInt(s.substring(start, i + 1)) >= 0&& Integer.parseInt(s.substring(start, i + 1)) <= 255; i++) {// 如果ip段的长度大于1,并且第一位为0的话,continueif (i + 1 - start > 1 && s.charAt(start) - '0' == 0) {continue;}stringBuilder.append(s.substring(start, i + 1));// 当stringBuilder里的网段数量小于3时,才会加点;如果等于3,说明已经有3段了,最后一段不需要再加点if (number < 3) {stringBuilder.append(".");}number++;restoreIpAddressesHandler(s, i + 1, number);number--;//回溯// 删除当前stringBuilder最后一个网段,注意考虑点的数量的问题stringBuilder.delete(start + number, i + number + 2);}}
}

时间复杂度:O(3^4);(IP地址最多包含4个数字,每个数字最多有3种可能的分割方式,则搜索树的最大深度为4,每个节点最多有3个子节点)

空间复杂度:O(n);(递归栈的深度最多为 n)


 Leetcode  78.子集

题目链接:78.子集

大佬视频讲解:子集视频讲解

个人思路

这是典型的子集问题,也就是找树的所有节点,利用回溯法,将所有节点都加入结果列表。

解法
回溯法

把求子集问题抽象为如下树形结构:

从图中红线部分,可以看出遍历这个树的时候,把所有节点都记录下来,就是要求的子集集合

回溯法三部曲

子集也是一种组合问题,因为它的集合是无序的,子集{1,2} 和 子集{2,1}是一样的。

1.递归函数参数

全局变量数组path为子集收集元素,二维数组result存放子集组合。(也可以放到递归函数参数里)

递归函数参数需要startIndex,因为求子集也是组合,组合是无序,取过的元素不会重复取,for就要从startIndex开始,而不是从0开始。

2.递归终止条件

如上图剩余集合为空的时候,就是叶子节点。也就是startIndex已经大于数组的长度了,就终止了,因为没有元素可取了

其实可以不需要加终止条件,因为startIndex >= nums.size(),本层for循环本来也结束了

3.单层搜索逻辑

求取子集问题,不需要任何剪枝!因为子集就是要遍历整棵树

class Solution {List<List<Integer>> result = new ArrayList<>();// 存放符合条件结果的集合LinkedList<Integer> path = new LinkedList<>();// 用来存放符合条件结果public List<List<Integer>> subsets(int[] nums) {subsetsHelper(nums, 0);return result;}private void subsetsHelper(int[] nums, int startIndex){result.add(new ArrayList<>(path));//把所有节点都记录下来,就是要求的子集集合if (startIndex >= nums.length){ //终止条件也可以不加return;}for (int i = startIndex; i < nums.length; i++){path.add(nums[i]);subsetsHelper(nums, i + 1);path.removeLast();//回溯}}
}

时间复杂度:O(n * 2^n));(循环n个元素,2^n表示所有可能的子集数量)

空间复杂度:O(n);(递归栈的深度最多为 n)


 Leetcode  90.子集II

题目链接:90.子集II

大佬视频讲解:子集II视频讲解

 个人思路

这道题和上面子集的区别就是,这道题里的集合里有重复元素了,而且求取的子集要去重,这就用到了之前组合问题中的同一层去重(树层去重), 去重要用到标记数组used

解法
回溯法

把子集问题抽象为如下树形结构

从图中可以看出,同一树层上重复取2 就要过滤掉同一树枝上可以重复取2,因为同一树枝上元素的集合才是唯一子集!

这道题的逻辑和 Leetcode  40.组合总和II 一样,搞清楚同一树层去重就能解决这道题。

class Solution {List<List<Integer>> result = new ArrayList<>();// 存放符合条件结果的集合LinkedList<Integer> path = new LinkedList<>();// 用来存放符合条件结果boolean[] used;//记录元素是否使用过,用来树层去重public List<List<Integer>> subsetsWithDup(int[] nums) {if (nums.length == 0){result.add(path);return result;}Arrays.sort(nums);used = new boolean[nums.length];//初始化一个全是false(0)的布尔数组subsetsWithDupHelper(nums, 0);return result;}private void subsetsWithDupHelper(int[] nums, int startIndex){result.add(new ArrayList<>(path));if (startIndex >= nums.length){return;}for (int i = startIndex; i < nums.length; i++){if (i > 0 && nums[i] == nums[i - 1] && !used[i - 1]){//树层重复continue;}path.add(nums[i]);used[i] = true;subsetsWithDupHelper(nums, i + 1);path.removeLast();//回溯used[i] = false;//回溯}}
}

时间复杂度:O(n * 2^n));(循环n个元素,2^n表示所有可能的子集数量)

空间复杂度:O(n);(递归栈的深度最多为 n)


 以上是个人的思考反思与总结,若只想根据系列题刷,参考卡哥的网址代码随想录算法官网

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

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

相关文章

#微信小程序:微信小程序常见的配置传值

微信小程序 app.js 设置全局的基础数据 通过 let app getApp() 获取里面的数据 app.json 设置tab,注册页面的路由 app.wxss 公共的样式&#xff0c;引入iconfont project.config.json 项目配置文件&#xff0c;用的最多就是配置是否开启https校验 pages 包含一个个…

2024最新版正规视频影视系统源码/APP+H5视频影视源码

全新魅思V20正规视频影视系统源码&#xff0c;APPH5视频影视源码。会员花费三千购入的&#xff0c;具体搭建教程放压缩包了&#xff01; 有兴趣的下载自行研究吧&#xff0c;搭建一共要用到3个域名&#xff0c;可以拿二级域名搭建。

C语⾔内存函数

目录 1. memcpy使⽤和模拟实现 memcpy函数的模拟实现: 2. memmove使⽤和模拟实现 memmove的模拟实现&#xff1a; 3. memset函数的使⽤ 4. memcmp函数的使⽤ 1. memcpy使⽤和模拟实现 void * memcpy ( void * destination, const void * source, size_t num ); • 函数me…

一周速递|全球车联网产业动态(2024年3月24日)

政策法规 1、3月19日&#xff0c;北京市委副书记、市长殷勇表示&#xff0c;北京市三年前开始率先采用车路协同技术路线&#xff0c;推进自动驾驶技术发展。以北京经济技术开发区为起点&#xff0c;将进一步深化自动驾驶和智慧城市建设的联动&#xff0c;继续在这个领域吸引更…

c语言函数大全(L开头)

c语言函数大全(L开头) There is no nutrition in the blog content. After reading it, you will not only suffer from malnutrition, but also impotence. The blog content is all parallel goods. Those who are worried about being cheated should leave quickly. 函数名…

Python文件读写操作

文件操作注意点 注意点&#xff1a; 1. for line in file --> 会将偏移量移到末尾 2. buffering1 --> 缓冲区中遇到换行就刷新&#xff0c;即向磁盘中写入 3. 读操作结束后&#xff0c;文本偏移量就会移动到读操作结束位置 """编写一个程序,循环不停的写入…

简述C语言文件操作

&#x1f308; 个人主页&#xff1a;白子寰 &#x1f525; 分类专栏&#xff1a;魔法指针&#xff0c;进阶C&#xff0c;C语言&#xff0c;C语言题集&#xff0c;C语言实现游戏&#x1f448; 希望得到您的订阅和支持~ &#x1f4a1; 坚持创作博文(平均质量分79)&#xff0c;分享…

数组划分,双指针

1 移动零 题目链接&#xff1a;https://leetcode.cn/problems/move-zeroes/description/ 这道题要在原数组中交换位置&#xff0c;并且还要求算法有稳定性。我们的常规思路是划分数组&#xff0c;用双指针解决。 public static void doubleIndex3(int[] arr){for(int cur 0…

计算机网络(特南鲍姆版) 期末总结

教材《计算机网络&#xff08;第六版&#xff09;》 特南鲍姆版 介绍 互联的可以交换信息的计算机称之为计算机网络&#xff0c;如&#xff1a;英特网 用途 1.访问信息 客户-服务器模型 peer-to-peer system&#xff08;点对点技术&#xff0c;P2P&#xff09; P2P&#xf…

深入理解Linux与Java的IO模型

目录 IO模型Linux的I/O模型Java的I/O模型联系与区别 同步&#xff0c;异步&#xff0c;阻塞&#xff0c;非阻塞同步与异步阻塞与非阻塞Linux I/O模型中的应用Java I/O模型中的应用容易混淆的地方 通过交互理解IO模型用户空间与内核空间Linux I/O模型的交互过程 在软件开发领域&…

加载三维模型,加载时黑的?

JS引擎是单线程 JS和渲染引擎线程无法同时进行&#xff0c;若异步任务和同步任务过多&#xff0c;JS引擎运行&#xff0c;渲染引擎未工作&#xff0c;导致黑黑的

Delphi DataSet转JSon(字符串拼接json)

Delphi中将TDataSet转换为JSon字符串。 function Test.DataSetToJson(ADataset: TDataSet): string; varARecord: string;AField: TField;i: integer; beginResult : ;with ADataset dobegin// 如果dataset是空就退出if IsEmpty thenExit;//初始化ARecordARecord : ;//定义开头…

图论基础|841.钥匙和房间、463. 岛屿的周长

目录 841.钥匙和房间 思路&#xff1a;本题是一个有向图搜索全路径的问题。 只能用深搜&#xff08;DFS&#xff09;或者广搜&#xff08;BFS&#xff09;来搜。 463. 岛屿的周长 841.钥匙和房间 力扣题目链接 (opens new window) 有 N 个房间&#xff0c;开始时你位于 0…

git 常用命令-以及命令解析

一、Push操作 1.先git init 标识仓库地址2.git add xxx git add . 代表添加当前目录所有文件代表标识提交的文件3.git commit -m xxxx 代表git提交后需要说的什么话4.git remote add origin xxxx xxxx替换为github仓库的ssh地址5.git push origin xxx xxx为分支名称如果有报错可…

TCP重传机制详解——03DSACK

TCP重传机制详解——03DSACK 什么是DSACK DSACK是指"Duplicate Selective Acknowledgment"&#xff0c;即重复选择性确认。在TCP通信中&#xff0c;DSACK机制允许接收方向发送方发送有关重复数据包的信息&#xff0c;以帮助发送方更准确地处理重传和丢包情况。 当…

C语言- 输出班级第n个学生的平均成绩

题目描述 输出班级第 n个学生的平均成绩。每个学生有英语、数学、语文、计算机 4 科成绩。若干个学生的 4 门成绩构成一个表格&#xff0c;可以用二维数组储存&#xff0c;每行代表一个学生的 4 门成绩。以为要计算某个学生的平均成绩&#xff0c;需要快速定位到该生成绩的起始…

概率论与数理统计-条件概率题目1-两次取球问题(有放回)

题目&#xff1a; 设袋中装有r只红球,t只白球.每次自袋中任取一只球,观察其颜色例3然后放回,并再放入a只与所取出的那只球同色的球.若在袋中连续取球四次&#xff0c;试求第一、二次取到红球且第三、四次取到白球的概率. 解答&#xff1a; 涉及到条件概率和多次独立事件的概…

ColorWell for Mac 直装激活 非常实用的调色工具

ColorWell 是一款为Mac操作系统设计的实用工具&#xff0c;它旨在帮助用户快速而方便地选择、管理和应用颜色。这款应用程序特别适合设计师、插画师、网页开发者以及任何需要精确颜色匹配的专业人士使用。ColorWell 的核心功能是提供一个简单直观的界面&#xff0c;让用户可以轻…

C++一维数组练习oj(3)

为什么C的一维数组练习要出要做那么多的题目&#xff1f;因为我们是竞赛学生&#xff01;想要将每个知识点灵活运用的话就必须刷大量的题目来锻炼思维。 我使用的是jsswoj.com这个刷题网站&#xff0c;当然要钱... C一维数组练习oj(2)-CSDN博客这是上一次的题目讲解 这道题有…

vscode集成git管理项目

一、git与SVN Git&#xff1a; 是一种分布式版本控制系统&#xff0c;每个开发者都可以在本地完整地复制整个代码仓库&#xff0c;并且可以在不连接到中央服务器的情况下进行提交、分支和合并等操作。 SVN &#xff1a;是一种集中式版本控制系统&#xff0c;开发者们只能直接与…