代码随想录算法训练营Day24
复原IP地址
类似于上题的分割回文串
给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式。有效的 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 '.' 分隔。
class Solution {
List<String> result = new ArrayList<>();
public List<String> restoreIpAddresses(String s) {
backtracking(s, 0, 0);
return result;
}
public void backtracking(String s,int start,int pointSum){//pointSum是逗号的个数
if(pointSum == 3){
if(isValid(s,start,s.length()-1)){
result.add(s);
}
return;
}
for(int i = start;i<s.length()-1;i++){
if(isValid(s,start,i)){
//插入.
s = s.substring(0, i + 1) + "." + s.substring(i + 1);
pointSum++;
backtracking(s,i+2,pointSum);//这里有.
//删除
pointSum--;
s = s.substring(0, i + 1) + s.substring(i + 2);
}else{
break;
}
}
}
private boolean isValid(String s, int start, int end) {
if (start > end) {
return false;
}
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;
}
}
子集
给你一个整数数组
nums,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
class Solution {
//之前的题在叶子节点收获结果,这道题在每个分支都取结果
List<List<Integer>> result = new ArrayList<>();
List<Integer> path = new ArrayList<>();
public List<List<Integer>> subsets(int[] nums) {
backTracking(nums,0);
return result;
}
public void backTracking(int[] nums,int startIndex){
result.add(new ArrayList<>(path));//每次进入一层递归,都将结果添加进path中
if(startIndex == nums.length){
//result.add(new ArrayList<>(path));这里和以前不一样
return;
}
for(int i = startIndex;i<nums.length;i++){
path.add(nums[i]);
backTracking(nums,i+1);
path.removeLast();
}
}
}
子集2
给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明:解集不能包含重复的子集。
与上面一题的区别在于,上面题不包含重复元素,而这道题包含重复元素,类似于之前的排序后再去重!
子集+组合总和2
class Solution {
//之前的题在叶子节点收获结果,这道题在每个分支都取结果
List<List<Integer>> result = new ArrayList<>();
List<Integer> path = new ArrayList<>();
boolean[] used;
public List<List<Integer>> subsetsWithDup(int[] nums) {
Arrays.sort(nums);
used = new boolean[nums.length];
backTracking(nums,0,used);
return result;
}
public void backTracking(int[] nums,int startIndex,boolean[] used){
result.add(new ArrayList<>(path));//每次进入一层递归,都将结果添加进path中
if(startIndex == nums.length){
//result.add(new ArrayList<>(path));这里和以前不一样
return;
}
for(int i = startIndex;i<nums.length;i++){
if (i>0 && nums[i - 1] == nums[i] && used[i-1]==false) continue;//后面条件保证了是树层上去重,**used[i]!=false**?
path.add(nums[i]);
used[i] = true;
backTracking(nums,i+1,used);
path.removeLast();
used[i] = false;
}
}
}
- 树层去重原理
当nums[i] == nums[i-1]时:
used[i-1]==false表示前一个相同元素未被使用(说明是树层去重)used[i-1]==true表示前一个元素在当前路径中被使用(是树枝上的重复)
- 第二段代码的问题
used[i]!=false条件在当前元素未被处理时永远为false:
- 当进入循环时,
used[i]初始值为false- 该条件会导致剪枝条件永远不成立
- 最终导致无法正确去重

浙公网安备 33010602011771号