[代码随想录Day24打卡] 93.复原IP地址 78.子集 90.子集II

93.复原IP地址

一个合法的IP地址是什么样的:
有3个’.'分割得到4个数,每个数第一个数不能是0,不能含有非法字符,不能大于255。
在这里插入图片描述
这个是否属于合法IP相当于一个分割问题,把一串字符串分割成4部分,分别判断每个部分是否合法,如果全部合法就保存结果,否则就return;
回溯三部曲

  1. 确定参数和返回值:参数要处理的字符串s,startIndex来防止我们重复分割和pointNum存储当前加的’.‘的个数。我们把path(存储当前的字符串)和result(存储加了’.'符合合法IP条件的字符串的结果列表)定义为了全局变量所以不需要返回值。
  2. 递归终止条件:if(pointNum==3)说明我们已经加了三个’.',然后直接判断最后一个数字是否合法,如果合法就保存结果,如果不合法就return。
  3. 单层递归逻辑:我们就是把整体字符串分段,分别判断每一段分割结果是否合法,如果合法就往字符串中加’.',并且递归调用backtracking进行下一次分割如果不合法就直接return不操作。
    当前分割的结果:startIndex指明当前循环中开始位置在这个循环过程中是不变的,i不断地向右循环,[startIndex, i]就是当前处理的字符串(就是IP地址中的一段,那段数字,我们只需要判断这段数字是否合法就可以)。
    分割标志:startIndex就是相当于分割标志,指明了前一次分割的位置。
    下面是C++、JAVA、Python的代码。
class Solution {
private:vector<string> result;bool isValid(const string& s, int start, int end){if(start>end){return false;}if(s[start]=='0' && start != end){//0开头的数字不合法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){//数字大于255不合法return false;}}return true;}void backtracking(string& s, int startIndex, int pointSum){if(pointSum == 3){//对最后一段的合法性进行判断if(isValid(s, startIndex, s.size()-1)){//result.push_back(s);}return;}//递归终止条件for(int i = startIndex; i < s.size(); i++){//单层递归if(isValid(s, startIndex, i)){s.insert(s.begin()+i+1, '.');pointSum += 1;backtracking(s, i+2, pointSum);s.erase(s.begin()+i+1);pointSum-=1;}}}
public:vector<string> restoreIpAddresses(string s) {if (s.size() < 4 || s.size() > 12) return result;backtracking(s, 0, 0);return result;}
};
class Solution {List<String> result = new ArrayList<>();//建立一个列表存储最终结果public List<String> restoreIpAddresses(String s) {backtracking(s, 0, 0);return result;}private void backtracking(String s, int startIndex, int pointNum){if(pointNum == 3){//如果逗号数量为3停止向下递归if(isValid(s, startIndex, s.length()-1)){result.add(s);}return;}for(int i = startIndex; i < s.length(); i++){//单层递归逻辑if(isValid(s, startIndex, i)){//如果合法s = s.substring(0, i+1) + "." + s.substring(i + 1);//在str的后面插入"."pointNum++;backtracking(s, i+2, pointNum);//pointNum--;//回溯s = s.substring(0, i+1) + s.substring(i+2);//回溯删掉逗点,substring一个参数是从beginIndex开始到末尾,有两个参数从 beginIndex 开始到 endIndex 结束前(不包括 endIndex)提取子字符串}else{break;}}}//判断字符串s在左闭右闭区间[start, end]所组成的数字是否合法private Boolean isValid(String s, int start, int end){if(start > end){return false;}//start和end本身就不合法if(s.charAt(start) == '0' && start != end){//0开头的数字不合法return false;}int num = 0;//这个是存储从字符串变成数字的数字for(int i = start; i <= end; i++){//判断每个字符的合法性if(s.charAt(i) > '9' || s.charAt(i)<'0'){return false;}num = num*10 + (s.charAt(i)-'0');//这个就是计算当前的数字if(num > 255){//如果大于255了不合法return false;}}return true;}
}
class Solution(object):def __init__(self):self.result = []def restoreIpAddresses(self, s):""":type s: str:rtype: List[str]"""if(len(s)<4 or len(s)>12):return self.resultself.backtracking(s, 0, 0)return self.resultdef backtracking(self, s, startIndex, pointNum):#递归终止条件if(pointNum == 3):if(self.isValid(s, startIndex, len(s)-1)):self.result.append(s)#如果合法就存入for i in range(startIndex, len(s)):if(self.isValid(s, startIndex, i)):s = s[:i+1]+'.'+s[i+1:]pointNum+=1#往字符串中加入一个点self.backtracking(s, i+2, pointNum)s = s[:i+1] + s[i+2:]pointNum -= 1#回溯def isValid(self, s, start, end):#判断所给字符的合法性,左闭右闭区间#首先判断传入的参数是否合法if(start > end):return False#判断是否开头有0if s[start] == '0' and start!=end:return Falsenum = 0#这个是存储当前这个子串对应的数值的for i in range(start, end+1):if s[i]>'9' or s[i]<'0':return False #判断每个字符是否合法num = num*10 + int(s[i])if(num > 255):return False#超出255非法return True

参考文章

  1. https://programmercarl.com/0093.%E5%A4%8D%E5%8E%9FIP%E5%9C%B0%E5%9D%80.html

78.子集

在这里插入图片描述遍历这个树的时候,把所有节点都记录下来,就是要求的子集集合。
注意:这个题目时每个节点的结果都要保存,不是只保存叶子节点。其他的和组合差不多。
回溯三部曲
1. 确定参数和返回值:参数就是数组nums和startIndex指示之前使用了那些元素,防止重复取数。我们把path金额result定义为全局变量,所以不需要返回值。
2. 遍历终止条件:startIndex>= nums.size() return;就是如果startIndex超出了数组的范围就停止递归。
单层递归的逻辑:i从startIndex到nums.size()遍历,每次遍历都把nums[i]当前元素加入到path当前结果中,然后backtracking()继续下层递归,然后path.pop_back()回溯。

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;}
};
class Solution {List<Integer> path = new LinkedList<>();List<List<Integer>> result = new ArrayList<>();public void backtracking(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]);backtracking(nums, i+1);path.removeLast();}}public List<List<Integer>> subsets(int[] nums) {backtracking(nums, 0);return result;}
}
class Solution(object):def __init__(self):self.result = []self.path = []def backtracking(self, nums, startIndex):self.result.append(list(self.path))#别忘了这个加list为了就是不指向同一个地址if(startIndex>=len(nums)):returnfor i in range(startIndex, len(nums)):self.path.append(nums[i])#存入元素self.backtracking(nums, i+1)self.path.pop()def subsets(self, nums):""":type nums: List[int]:rtype: List[List[int]]"""self.backtracking(nums, 0)return self.result

参考文章

  1. https://programmercarl.com/0078.%E5%AD%90%E9%9B%86.html

90.子集II

在这里插入图片描述
这个就是子集和组合Ⅱ的应用。
秒了。
注意

  1. 对于有重复元素的题目,要去重,先排序。
  2. 设置used数组来判断时树枝还是树层。每个语言怎么定义要清楚。
  3. 保存结果的时候要根据每个语言,JAVA和Python都是需要处理一下path再加入到result中,不然result中的元素都指向同一个位置,最后结果都[]
  4. 去重的两行代码要记住。

回溯三部曲

  1. 确定参数和返回值:参数时数组nums和startIndex,返回值为None。
  2. 递归终止条件:看startIndex是否越界,如果越界就直接返回。没有也可以,因为后面for循环也会因为startIndex越界不运行直接return。
  3. 单层递归逻辑:加入去重的两行代码if(i>0 && nums[i]==nums[i-1] && used[i-1]==0)continue;(直接跳过,到不是重复的数,不是break,break会漏掉重复数字之后的所有的数字)然后把当前数字放到path中,更新used使当前索引的位置used[i]=true,然后backtracking()递归处理下一个数,path.pop(),used[i]=false回溯一下。
class Solution {
private:vector<int> path;vector<vector<int>> result;void backtracking(vector<int>& nums, int startIndex, vector<bool> used){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] && used[i-1]==0){continue;//跳过重复元素}path.push_back(nums[i]);used[i] = true;backtracking(nums, i+1, used);used[i] = false;path.pop_back();}}
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;}
};
class Solution {List<Integer> path = new LinkedList<>();List<List<Integer>> result = new ArrayList<>();public void backtracking(int[] nums, int startIndex, boolean[] used){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] == false){continue;}path.add(nums[i]);used[i] = true;backtracking(nums, i+1, used);used[i] = false;path.removeLast();}}public List<List<Integer>> subsetsWithDup(int[] nums) {boolean[] used = new boolean[nums.length];Arrays.fill(used, false);Arrays.sort(nums);backtracking(nums, 0, used);return result;}
}
class Solution(object):def __init__(self):self.result = []self.path = []def backtracking(self, nums, startIndex, used):self.result.append(list(self.path))if(startIndex>=len(nums)):#递归终止条件也可以不写returnfor i in range(startIndex, len(nums)):if(i>startIndex and nums[i] == nums[i-1] and not used[i-1]):continue#去重self.path.append(nums[i])used[i] = Trueself.backtracking(nums, i+1, used)used[i] = Falseself.path.pop()def subsetsWithDup(self, nums):""":type nums: List[int]:rtype: List[List[int]]"""nums.sort()#别忘了排序used = [False]*len(nums)self.backtracking(nums, 0, used)return self.result

参考文章

  1. https://programmercarl.com/0090.%E5%AD%90%E9%9B%86II.html

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

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

相关文章

Java学习笔记--继承方法的重写介绍,重写方法的注意事项,方法重写的使用场景,super和this

目录 一&#xff0c;方法的重写 二&#xff0c;重写方法的注意事项 三&#xff0c;方法重写的使用场景 四&#xff0c;super和this 1.继承中构造方法的特点 2.super和this的具体使用 super的具体使用 this的具体使用 一&#xff0c;方法的重写 1.概述:子类中有一个和父类…

gRPC 双向流(Bidirectional Streaming RPC)的使用方法

gRPC 是一个支持多种语言的高性能 RPC 框架&#xff0c;拥有丰富的 API 来简化服务端和客户端的开发过程。gRPC 支持四种 RPC 类型&#xff1a;Unary RPC、Server Streaming RPC、Client Streaming RPC 和 Bidirectional Streaming RPC。下面是双向流 API 的使用方法。 双向流…

npm install -g@vue/cli报错解决:npm error code ENOENT npm error syscall open

这里写目录标题 报错信息1解决方案 报错信息2解决方案 报错信息1 使用npm install -gvue/cli时&#xff0c;发生报错&#xff0c;报错图片如下&#xff1a; 根据报错信息可以知道&#xff0c;缺少package.json文件。 解决方案 缺什么补什么&#xff0c;这里我们使用命令npm…

【ComfyUI】前景分割ComfyUI-BiRefNet-Hugo (无法选定分割的主体,背景鉴别由模型数据,也叫二分分割,显著性分割)

源码&#xff1a;https://github.com/ZhengPeng7/BiRefNet comfyui插件&#xff1a;https://github.com/MoonHugo/ComfyUI-BiRefNet-Hugo 模型下载地址&#xff1a;https://huggingface.co/ZhengPeng7/BiRefNet 工作流以及相关资源下载&#xff1a;https://pan.baidu.com/s/1-U…

大数据技术之Spark :我快呀~

在 MapReduce 为海量数据的计算服务多年后&#xff0c;随着时代的发展和 Spark 等新技术的出现&#xff0c;它的劣势也慢慢的凸显出来了&#xff1a; 执行速度慢。编程复杂度过高。 先看第一点 2000 年代诞生的 MapReduce &#xff0c;因为计算资源有限&#xff0c;所以 Map…

新160个crackme - 105-royalaccezzcrackme

运行分析 需破解Name和Serial&#xff0c;点击OK没反应 PE分析 ASM程序&#xff0c;32位&#xff0c;无壳 静态分析&动态调试 ida找到关键字符串 进行静态分析&#xff0c;逻辑如下&#xff1a;1、Name长度大于4&#xff0c;小于212、fun_1返回值为1 对func_1进行动态调试分…

【RISC-V CPU 专栏 -- 香山处理器介绍】

文章目录 RISC-V 香山处理器介绍雁栖湖处理器南湖处理器RISC-V 香山处理器介绍 相信很多小伙伴对于“香山”都不陌生,它是一款开源RISC-V处理器核,香山的每一代架构,都是采用了湖的名字,第一代架构被命名为雁栖湖,第二代架构则叫做 “南湖”。 “雁栖湖”这款处理器的 R…

远程视频验证如何改变商业安全

如今&#xff0c;商业企业面临着无数的安全挑战。尽管企业的形态和规模各不相同——从餐厅、店面和办公楼到工业地产和购物中心——但诸如入室盗窃、盗窃、破坏和人身攻击等威胁让安全主管时刻保持警惕。 虽然传统的监控摄像头网络帮助组织扩大了其态势感知能力&#xff0c;但…

【TQ2440】02 串口连接进入u-boot

需要收到的板子已经烧写好系统或u-boot&#xff0c;看开机液晶屏底下的四个LED灯有没有亮黄绿色&#xff0c;没有就是还没烧写u-boot&#xff0c;需要先使用Jlink烧写u-boot 进入 uboot 的下载模式&#xff0c;如果从 Nor Flash 启动默认的就是进入 uboot 的下载模式&#xff…

QCommandLinkButton控件 全面详解

本系列文章全面的介绍了QT中的57种控件的使用方法以及示例,包括 Button(PushButton、toolButton、radioButton、checkBox、commandLinkButton、buttonBox)、Layouts(verticalLayout、horizontalLayout、gridLayout、formLayout)、Spacers(verticalSpacer、horizontalSpacer)、…

【Vue】Ego商城项目跟做

技术栈 Vue全家桶&#xff1a;Vue VueRouter Vuex Axios ElementUI 依赖安装 网络请求&#xff1a;npm install --save axios --no-fund Element&#xff1a;vue add element 后端相关依赖&#xff1a;npm install --save express cors mysql --no-fund token&#xff1a;np…

python简单算法

冒泡 def boll(lis):i 0while i<len(lis)-1:j 0while j<len(lis)-1-i:if lis[j] > lis[j1]:lis[j],lis[j 1] lis[j1],lis[j]j1i1选择排序 def selct1(lit):i 0while i<len(lit)-1:j i1min1 iwhile j < len(lit):if lit[j] < lit[min1]:min1 jj 1li…

2024年第15届蓝桥杯C/C++组蓝桥杯JAVA实现

目录 第一题握手&#xff0c;这个直接从49累加到7即可&#xff0c;没啥难度&#xff0c;后面7个不握手就好了&#xff0c;没啥讲的&#xff0c;(然后第二个题填空好难&#xff0c;嘻嘻不会&#xff09; 第三题.好数​编辑 第四题0R格式 宝石组合 数字接龙 最后一题:拔河 第…

【Docker】常用命令汇总

Docker 是1个开源的应用容器引擎&#xff0c;基于Go 语言并遵从 Apache2.0 协议开源。 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中&#xff0c;然后发布到任何流行的 Linux 机器上&#xff0c;也可以实现虚拟化。 容器是完全使用沙箱机制&#xff0c;相…

如何选择最适合企业的ETL解决方案?

在今天的大数据时代&#xff0c;企业的数据管理和处理变得愈发重要。企业也越来越依赖于数据仓库和数据湖来提取、转换和加载&#xff08;ETL&#xff09;关键业务信息。一个高效、灵活的ETL解决方案不仅能提升数据处理能力&#xff0c;还能为企业决策提供有力支持。然而&#…

EG3D: Efficient Geometry-aware 3D Generative Adversarial Networks 学习笔记

1 Contributions 混合显式-隐式网络架构&#xff1a;提出了一种 Tri-plane 的3D表征方法&#xff0c;结合显式体素网格与隐式解码器的优点 速度快&#xff0c;内存效率高&#xff1b; 支持高分辨率生成&#xff0c;保持3D表征的灵活性和表达能力。与纯显式或隐式方法相比&#…

第十六届蓝桥杯模拟赛(第一期)-Python

本次模拟赛我认为涉及到的知识点&#xff1a; 分解质因数 Python的datetime库 位运算 简单dp 1、填空题 【问题描述】 如果一个数 p 是个质数&#xff0c;同时又是整数 a 的约数&#xff0c;则 p 称为 a 的一个质因数。 请问 2024 有多少个质因数。 【答案提交】 这是一道结…

ubuntu 安装 docker 记录

本文假设系统为 Ubuntu&#xff0c;从 16.04 到 24.04&#xff0c;且通过 APT 命令安装。理论上也其他 Debian 系的操作系统。 WSL 也一样。 感觉 Docker 官方在强推 Docker Desktop&#xff0c;搜索 Docker 安装文档&#xff0c;一不小心就被导航到了 Docker Desktop 的安装页…

太速科技-512-基于ZU19EG的4路100G 8路40G的光纤汇流计算卡

基于ZU19EG的4路100G 8路40G的光纤汇流计算卡 一、板卡概述 本板卡系我司自主设计研发&#xff0c;基于Xilinx公司Zynq UltraScale MPSOC系列SOC XCZU19EG-FFVC1760架构&#xff0c;ARM端搭载一组64-bit DDR4&#xff0c;总容量达4GB&#xff0c;可稳定运行在2400MT/s…

C#基础56-60

56.字符数组x中存有任意一串字符&#xff1b;串中的所有小写字母改写成大写字母&#xff0c;如果是大写字母改为小写字母&#xff0c;其他字符不变。最后把已处理的字符串仍重新存入字符数组x中&#xff0c;最后调用函数把结果输出到控制台中。 57.求出100以上1000以内所有个位…