参考资料:
https://programmercarl.com/0093.%E5%A4%8D%E5%8E%9FIP%E5%9C%B0%E5%9D%80.html
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"]
思路分析:
参数:字符串,切割位,已满足要求的段数
递归终止条件:1.符合要求的地址,收进结果集 2.不符合要求的return
单层递归:for循环遍历——每层递归取数的过程
注意:回溯过程中 stringB.delete(start+num,i+num+2)的理解
代码实现:
class Solution {
List<String> res=new ArrayList<>();
StringBuilder stringB=new StringBuilder();
public List<String> restoreIpAddresses(String s) {
if(s.length()>12) return res;
backTrack(s,0,0);
return res;
}
private void backTrack(String s ,int start,int num){//前面已分割好的段
if(start==s.length() && num==4){//符合要求,收集结果
res.add(stringB.toString());
return;
}
if(start==s.length() || num==4){//不符合
return;
}
//单层递归逻辑
for(int i=start;i<s.length();i++){
//剪枝
if(i-start<3 && Integer.parseInt(s.substring(start,i+1))>=0 && Integer.parseInt(s.substring(start,i+1))<=255){//substring左闭右开
//大于一位,首位为‘0’的不要
if(i-start>0 && s.charAt(start)-'0'==0) break;//???continue
stringB.append(s.substring(start,i+1));
if(num<3) stringB.append('.');//最后一段不用加'.'
num++;
backTrack(s,i+1,num);
num--;
stringB.delete(start+num,i+num+2);//具体看图理解
}
}
}
}
78. 子集
题目描述:
给你一个整数数组 nums
,数组中的元素 互不相同 。返回该数组所有可能的
子集
(幂集)。
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
示例 1:
输入:nums = [1,2,3] 输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
思路分析:
每个树节点都要收集
代码实现:
class Solution {
List<List<Integer>> res=new ArrayList<>();
LinkedList<Integer> path=new LinkedList<>();
public List<List<Integer>> subsets(int[] nums) {
backTracking(nums,0);
return res;
}
public void backTracking(int[] nums,int start){
//每个结果都要收集
res.add(new ArrayList<>(path));
if(start>=nums.length){//该终止条件可不写,后面for循环处也会判断
return;
}
for(int i=start;i<nums.length;i++){//每层递归取数的过程
path.add(nums[i]);
backTracking(nums,i+1);//下一层递归,树的更深一层
path.removeLast();
}
}
}
90. 子集 II
题目描述:
给你一个整数数组 nums
,其中可能包含重复元素,请你返回该数组所有可能的
子集
(幂集)。
解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。
示例 1:
输入:nums = [1,2,2] 输出:[[],[1],[1,2],[1,2,2],[2],[2,2]]
思路分析:
用used数组进行树层去重(树枝不用去重)
若nums[i]==nums[i-1] && used[i-1]==false时,就是需要去重了
代码实现:
class Solution {
List<List<Integer>> res=new ArrayList<>();
LinkedList<Integer> path=new LinkedList<>();
boolean[] used;
public List<List<Integer>> subsetsWithDup(int[] nums) {
used=new boolean[nums.length];
Arrays.sort(nums);
backTracking(nums,0,used);
return res;
}
public void backTracking(int[] nums,int start,boolean[] used){
//每个节点都收集
res.add(new ArrayList<>(path));
for(int i=start;i<nums.length;i++){
if(i>0 && nums[i]==nums[i-1] && !used[i-1]) continue;//树层去重,树枝不用去重
path.add(nums[i]);
used[i]=true;
backTracking(nums,i+1,used);
path.removeLast();
used[i]=false;
}
}
}