算法打卡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的话,continue
			if (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)


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

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

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

相关文章

二维码门楼牌管理应用平台建设:提升城市管理效率的新路径

文章目录 前言一、二维码门楼牌管理应用平台的建设背景二、人工数据审核的重要性三、地址匹配校验的作用四、数据修改后的状态管理五、二维码门楼牌管理应用平台的未来展望 前言 随着城市管理的不断升级&#xff0c;二维码门楼牌管理应用平台正逐渐成为城市管理的新宠。本文将…

今天简单聊聊容器化

什么是容器化 容器化&#xff08;Containerization&#xff09;是一种软件开发和部署的方法&#xff0c;其核心思想是将应用程序及其所有依赖项打包到一个独立的运行环境中&#xff0c;这个环境被称为容器。容器化技术使得应用程序可以在不同的计算环境中以一致的方式运行&…

制作一个RISC-V的操作系统七-UART初始化(UART NS16550A 规定 目标 发送数据 代码 extern)

文章目录 UARTNS16550A规定目标发送数据代码extern UART 对应到嵌入式开发中&#xff0c;qemu模拟的就是那块开发板&#xff08;硬件&#xff09; 电脑使用qemu时可以理解为qemu模拟了那块板子&#xff0c;同时那块板子与已经与你的电脑相连接了&#xff08;我们对应的指定的内…

尽可能使用清晰、统一的方式初始化所有对象:列表初始化。【C++】

不管是为了统一性&#xff0c;还是避免发生窄化转换&#xff0c;尽可能使用初始化列表。 说明哪些对象可以使用列表初始化&#xff1f;代码演示 说明 C11 引入了列表初始化&#xff08;也称为统一初始化或初始化列表&#xff09;&#xff0c;它是一种使用花括号 {} 来初始化对…

【开奖】京东云活动大更新 全网比价 轮盘抽奖 云服务器选购推荐 阿里云 腾讯云 京东云采购季活动大盘点

已开奖&#xff0c;本次奖品&#xff1a;4核16G名额&#xff1a;首次抽奖 1名→3名&#xff01; 公布幸运儿&#xff1a;-阿纬-、不问青春、灰飞の慕沐 开奖地址&#xff1a; 【云服务器推荐】京东云活动大更新 另有开奖环节https://www.bilibili.com/video/BV1Vu4m1u7Qd 《…

通过rmi实现远程rpc(可以认为java自带Dubbo RPC)

背景&#xff1a; 发现公司几个运行10年的游戏&#xff0c;用的竟然是rmi&#xff0c;而我只听说过dubbo 和 基于netty的rpc&#xff0c;于是就补充了下rmi。 其次&#xff0c;是最近对于跨服的思考&#xff0c;如何避免回调也需要用同步写法&#xff0c;rmi比较适合。 1)api…

【智能算法】飞蛾扑火算法(MFO)原理及实现

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献 1.背景 2015年&#xff0c;Mirjalili等人受到飞蛾受到火焰吸引行为启发&#xff0c;提出了飞蛾算法(Moth-Flame Optimization&#xff0c;MFO)。 2.算法原理 2.1算法思想 MFO基于自然界中飞蛾寻找光源的…

(Windows)YOLOv8成功运行DCNv4报错总结

介绍 DCNv4是可变形卷积的第四版本也是今年2024年1月份公示的&#xff0c;其在网络结构上和DCNv3是差不多的&#xff0c;最突出的优点的减小了内存访问带来的负担&#xff0c;加快收敛的速度&#xff0c;在不失精度的情况下能把速度大幅度提升&#xff0c;在论文作者的实验里面…

yolov5交互式界面 V5.0-6.0版本通用界面-yolo-pyqt-gui(通用界面制作+代码)

往期热门博客项目回顾&#xff1a; 计算机视觉项目大集合 改进的yolo目标检测-测距测速 路径规划算法 图像去雨去雾目标检测测距项目 交通标志识别项目 yolo系列-重磅yolov9界面-最新的yolo 姿态识别-3d姿态识别 深度学习小白学习路线 yolo GUI OYQT界面 YOLOv5…

美国socks5动态IP代理如何提升网络效率?

在探讨美国socks5代理动态IP的奥秘之前&#xff0c;我们需要先深入理解其背后的基本概念和原理。Socks5代理是一种先进的网络协议&#xff0c;它像一位中转站&#xff0c;默默地帮用户转发网络请求。它让网络流量得以通过代理服务器传输&#xff0c;进而隐藏用户的真实IP地址。…

餐饮连锁食品安全标准落实难?悠络客AI巡检,用SOP AI化守护“舌尖上的安全”

食品安全与卫生问题一直是全民关注的焦点&#xff0c;从民生角度&#xff0c;民以食为天&#xff0c;食品安全关系到消费者的身体健康和生命安全&#xff1b;从企业角度&#xff0c;品牌建设不易&#xff0c;一旦出现食品卫生安全问题&#xff0c;不仅会带来直接经济损失&#…

Python灰帽子网络安全实践

教程介绍 旨在降低网络防范黑客的入门门槛&#xff0c;适合所有中小企业和传统企业。罗列常见的攻击手段和防范方法&#xff0c;让网站管理人员都具备基本的保护能力。Python 编程的简单实现&#xff0c;让网络运维变得更简单。各种黑客工具的理论和原理解剖&#xff0c;让人知…

【SpringCloud】探索Eureka注册中心

&#x1f3e1;浩泽学编程&#xff1a;个人主页 &#x1f525; 推荐专栏&#xff1a;《深入浅出SpringBoot》《java对AI的调用开发》 《RabbitMQ》《Spring》《SpringMVC》《项目实战》 &#x1f6f8;学无止境&#xff0c;不骄不躁&#xff0c;知行合一 文章目录 …

2核4g服务器能支持多少人访问?阿里云2核4g服务器在线人数

阿里云2核4G服务器多少钱一年&#xff1f;2核4G配置1个月多少钱&#xff1f;2核4G服务器30元3个月、轻量应用服务器2核4G4M带宽165元一年、企业用户2核4G5M带宽199元一年。可以在阿里云CLUB中心查看 aliyun.club 当前最新2核4G服务器精准报价、优惠券和活动信息。 阿里云官方2…

RPA使用Native Messaging 协议实现浏览器自动化

RPA 即机器人流程自动化&#xff0c;是一种利用软件机器人或人工智能来自动化业务流程中规则性、重复性任务的技术。RPA 技术可以模拟和执行人类在计算机上的交互操作&#xff0c;从而实现自动化处理数据、处理交易、触发通知等任务。帮助企业或个人实现业务流程的自动化和优化…

Springboot项目结构

1. 一个正常的企业项目里一种通用的项目结构和代码层级划分的指导意见&#xff1a; 一般分为如下几层&#xff1a; 开放接口层 终端显示层 Web 层 Service 层 Manager 层 DAO 层 外部接口或第三方平台 2. 以当下非常火热的Spring Boot典型项目结构为例&#xff0c;创建出…

政安晨:【深度学习实践】【使用 TensorFlow 和 Keras 为结构化数据构建和训练神经网络】(三)—— 随机梯度下降

政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: TensorFlow与Keras实战演绎 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff01; 这篇文章中&#xff0c;咱们将使用Keras和TensorFlow…

yolov8数据集制作——labelimg

一、为什么我们选择用labelimg标注yolov8数据集 它可以标注三种格式的数据 1 VOC标签格式&#xff0c;保存为xml文件。2 yolo标签格式&#xff0c;保存为txt文件。3 createML标签格式&#xff0c;保存为json格式。二、我们为什么不用labelimg标注yolo数据集 因为它只能标注…

网络——套接字编程UDP

目录 端口号 源端口号和目的端口号 认识TCP协议和UDP协议 网络字节序 socket编程接口 socket常见接口 sockaddr结构 UDP socket bind recvfrom sendto 编写客户端 绑定INADDR_ANY 实现聊天功能 端口号 在这之前我们已经说过源IP地址和目的IP地址&#xff0c;还有…

Ubuntu安装教程——Desktop版本(细致入微的操作)

目录 前言 一、安装Ubuntu桌面版操作系统 二、UbuntuLive版安装 1.语言选择 2.键盘布局 3.版本选择 4.网络配置 5.代理配置 6.镜像地址 7.磁盘划分 8.设置用户信息 9.ssh 10.选择软件包 11.安装界面 12.基础配置 12.1root用户 12.2时区 12.3包管理工具 12…