Day24补代码随想录20250108 93.复原IP地址|78.子集|90.子集II
93.复原IP地址
题目
有效 IP 地址 正好由四个整数(每个整数位于 0
到 255
之间组成,且不能含有前导 0
),整数之间用 '.'
分隔。
- 例如:
"0.1.2.201"
和"192.168.1.1"
是 有效 IP 地址,但是"0.011.255.245"
、"192.168.1.312"
和"192.168@1.1"
是 无效 IP 地址。
给定一个只包含数字的字符串 s
,用以表示一个 IP 地址,返回所有可能的 有效 IP 地址 ,这些地址可以通过在 s
中插入 '.'
来形成。你 不能 重新排序或删除 s
中的任何数字。你可以按 任何 顺序返回答案。
示例 1:
输入:s = "25525511135" 输出:["255.255.11.135","255.255.111.35"]
示例 2:
输入:s = "0000" 输出:["0.0.0.0"]
示例 3:
输入:s = "101023" 输出:["1.0.10.23","1.0.102.3","10.1.0.23","10.10.2.3","101.0.2.3"]
提示:
1 <= s.length <= 20
s
仅由数字组成
思路
- 参数和返回值,startIndex(记录下一层递归分割的起始位置),pointNum记录添加逗点的数量。
- 思路
- 主函数public List
<String>
restoreIpAddresses(String s)- 剪枝,当长度>12,一定不符合条件
- backTracking(s,0,0);
- return result;
- backTracking(String s,int startIndex,int pointNum)
- 终止条件,逗号数量pointNum=3,最后还有一段没有判断
- 判断第四段子字符串是否合法,如果合法就放进result中 [startIndex,s.length()-1]
- for循环
- 如果合法 if(isValid(s,startIndex,i))就递归回溯
- 处理节点, s=s.substring(0,i+1)+“.”+s.substring(i+1); //[)中间插入,其中后项为[i+1,末尾]的s值
- pointNum++;
- 递归
- 回溯
- pointNum–;
- s=s.substring(0,i+1)+s.substring(i+2);
- 如果合法 if(isValid(s,startIndex,i))就递归回溯
- isValid(String s,int start,int end)
- start>end
- 不是数字0的开头0不合法
- for
- 遇到非数字字符
- 大于255不合法
- 主函数public List
- 代码
class Solution { List<String> result=new ArrayList<>(); public List<String> restoreIpAddresses(String s) { if(s.length()>12) return result;//剪枝,一定不符合条件 backTracking(s,0,0); return result; } // startIndex: 搜索的起始位置, pointNum:添加逗点的数量 public void backTracking(String s,int startIndex,int pointNum){ //终止条件,逗点数量=,但是后面还剩一段没有判断 if(pointNum==3){ //判断第四段子字符串是否合法,如果合法就放进result中 if(isValid(s,startIndex,s.length()-1)){ result.add(s); } return; } //for循环 for(int i=startIndex;i<s.length();i++){ if(isValid(s,startIndex,i)){ s=s.substring(0,i+1)+"."+s.substring(i+1); //[)中间插入,其中后项为[i+1,末尾]的s值 pointNum++; backTracking(s,i+2,pointNum);//插入逗点之后下一个字串的起始位置为i+2 pointNum--;//回溯 s=s.substring(0,i+1)+s.substring(i+2);//回溯删除, }else{ break; } } } // 判断字符串s在左闭⼜闭区间[start, end]所组成的数字是否合法 private Boolean isValid(String s,int start,int end){ //特殊的false情况1,始末颠倒 if(start>end){ return false; } //开头为0不合法,但是整数可以时单0 if(s.charAt(start)=='0'&&start!=end){ return false; } int num=0; for(int i=start;i<=end;i++){ //遇到非数字字符 if(s.charAt(i)>'9'||s.charAt(i)<'0'){ return false; } //大于255不合法 num=num*10+(s.charAt(i)-'0'); if(num>255){ return false; } } return true; } }
总结
- startIndex是一定需要的,不能重复分割,记录下一层递归分割的起始位置。
- 情况很复杂,判断情况多,需要考虑得很全面,这道题挺难的。
78.子集
题目
【收集树形结构中每一个节点的结果】
给你一个整数数组 nums
,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
示例 1:
输入:nums = [1,2,3] 输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
示例 2:
输入:nums = [0] 输出:[[],[0]]
提示:
1 <= nums.length <= 10
-10 <= nums[i] <= 10
nums
中的所有元素 互不相同
思路
- 思路
- 收获结果的时候要取每一个节点的结果
-
class Solution { List<List<Integer>> result=new ArrayList<>(); List<Integer> path=new LinkedList<>(); public List<List<Integer>> subsets(int[] nums) { backTracking(nums,0); return result; } 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(); } } }
总结
- 注意result.add(new ArrayList<>(path));//提前加进去结果,以免遗漏最后一个值 这句代码要加在终止条件之前,以免遗漏
90.子集II
题目
【40.组合总和II和78.子集的结合】这道题用于测试我的学习效果
给你一个整数数组 nums
,其中可能包含重复元素,请你返回该数组所有可能的子集(幂集)。解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。
示例 1:
输入:nums = [1,2,2] 输出:[[],[1],[1,2],[1,2,2],[2],[2,2]]
示例 2:
输入:nums = [0] 输出:[[],[0]]
提示:
1 <= nums.length <= 10
-10 <= nums[i] <= 10
思路
-
40.组合总和II和78.子集的结合
class Solution { List<List<Integer>> result=new ArrayList<>(); List<Integer> path=new LinkedList<>(); public List<List<Integer>> subsetsWithDup(int[] nums) { Arrays.sort(nums); backTracking(nums,0); return result; } public void backTracking(int[] nums,int startIndex){ //提前保存结果 result.add(new ArrayList<>(path)); //终止条件 遍历到叶子节点 if(startIndex>nums.length){ return; } //for 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.removeLast(); } } }
总结
- 两个题的结合,没什么新知识点。
- startIndex树层去重+保存每个节点