day25 90. 子集 II&&78. 子集&&93.复原IP地址
- 子集 II
问题描述:给定一个可能包含重复数字的数组 nums,返回其所有不重复的子集。
代码实现:
排序:首先对数组进行排序,以便后续处理重复元素。
深度优先搜索(DFS):
使用递归的方式生成所有子集。
在递归过程中,通过 path 记录当前路径,start 表示当前搜索的起始位置。
每次递归时,将当前路径加入结果集 res。
遍历数组时,跳过重复的数字(if (i > start && nums[i] == nums[i - 1]) continue;)以避免重复子集。
通过回溯(path.removeLast())尝试所有可能的子集。
关键点:
排序数组以处理重复元素。
使用回溯法生成所有子集。
跳过重复的数字以避免重复子集。
//90. 子集 II
点击查看代码
public List<List<Integer>> subsetsWithDup(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
dfsSubsetsWithDup(nums,res,path,0);
return res;
}
private void dfsSubsetsWithDup(int[] nums, List<List<Integer>> res,LinkedList<Integer> path,int start) {
res.add(new LinkedList<>(path));
if (start == nums.length) return;
for (int i = start; i < nums.length; i++) {
if(i>start&&nums[i]==nums[i-1]) continue;
path.add(nums[i]);
dfsSubsetsWithDup(nums, res, path, i + 1);
path.removeLast();
}
}
- 子集
问题描述:给定一个不含重复数字的数组 nums,返回其所有可能的子集。
代码实现:
深度优先搜索(DFS):
使用递归的方式生成所有子集。
在递归过程中,通过 path 记录当前路径,start 表示当前搜索的起始位置。
每次递归时,将当前路径加入结果集 res。
遍历数组时,将当前数字加入路径,递归搜索下一个数字,然后通过回溯(path.removeLast())尝试其他可能的子集。
关键点:
使用回溯法生成所有子集。
不需要处理重复元素(因为输入数组不含重复数字)。
//78. 子集
点击查看代码
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
dfsSubsets(nums,res,path,0);
return res;
}
private void dfsSubsets(int[] nums, List<List<Integer>> res,LinkedList<Integer> path,int start) {
res.add(new LinkedList<>(path));
if (start == nums.length) return;
for (int i = start; i < nums.length; i++) {
path.add(nums[i]);
dfsSubsets(nums, res, path, i + 1);
path.removeLast();
}
}
- 复原 IP 地址
问题描述:给定一个只包含数字的字符串 s,返回所有可能的复原 IP 地址。
代码实现:
深度优先搜索(DFS):
使用递归的方式尝试将字符串分割成合法的 IP 地址。
在递归过程中,通过 path 记录当前分割的数字,start 表示当前分割的起始位置。
当分割出 4 个数字且遍历完整个字符串时,将当前路径拼接成 IP 地址并加入结果集 res。
遍历字符串时,尝试截取长度为 1 到 3 的子串:
如果截取的数字以 0 开头且长度大于 1,则跳过(IP 地址段不能以 0 开头)。
如果截取的数字大于 255,则跳过(IP 地址段必须在 0 到 255 之间)。
如果截取的数字为 0,则直接添加并递归,避免继续尝试更长的子串。
通过回溯(path.removeLast())尝试所有可能的分割方式。
关键点:
使用回溯法尝试所有可能的分割方式。
验证每个分割出的数字是否合法(是否以 0 开头、是否在 0 到 255 之间)。
当分割出 4 个数字且遍历完整个字符串时,生成合法的 IP 地址。
点击查看代码
//93.复原IP地址
public List<String> restoreIpAddresses(String s) {
List<String> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
dfsRestoreIpAddresses(s,res,path,0);
return res;
}
private void dfsRestoreIpAddresses(String s, List<String> res, LinkedList<Integer> path,int start) {
if (start == s.length()&&path.size()==4) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < path.size(); i++) {
sb.append(path.get(i));
if (i<path.size()-1){
sb.append(".");
}
}
res.add(sb.toString());
}
for (int i = 1; i+start <= s.length()&&i<=3; i++) {//最大是3位数
int num ;
if(path.size()<3){
num = Integer.parseInt(s.substring(start, i+start));
}else {//已截取出三个整数,最后部分形成第四个整数
if (s.charAt(start) == '0'&&start!=s.length()-1) {//整数不可以0开头
return;
}
if(s.length()-start>3) return;//不可超过3位数
num = Integer.parseInt(s.substring(start));
i=s.length()-start;
}
if(num==0){//整数不可以0开头,只能截取数字“0”,故不再循环后面的截取
path.add(num);
dfsRestoreIpAddresses(s, res, path, start+i);
path.removeLast();
return;
}else if(num<=255&&num>0){
path.add(num);
dfsRestoreIpAddresses(s, res, path, start+i);
path.removeLast();
}else {//截取超出范围,不再执行
return;
}
}
}

浙公网安备 33010602011771号