回溯模板:
backtrack() {
if(终止) {
放入结果集合;
return;
}
for(本层集合中元素) {
处理节点;
backtrack();//递归
回溯,恢复现场;
}
}
93.复原IP地址
思路:把点看作分割的位置,套用回溯模板
public void backtracking(StringBuilder s,int start, int point) {
if(point == 3) {
if(isVaild(s,start,s.length()-1))
result.add(s.toString());
return;
}
for(int i=start;i<s.length();i++) {
if(isVaild(s,start,i)) {
s.insert(i+1,'.');
backtracking(s,i+2,point+1);
s.deleteCharAt(i+1);
}else break;
}
}
终止时,如果有三个点了,判断最后一部分是否合法,如果最后什么也没有,也就是start为s.length,那么就不合法
private boolean isVaild(StringBuilder s, int start, int end){
if(start > end)
return false;
if(s.charAt(start) == '0' && start != end)
return false;
int num = 0;
for(int i = start; i <= end; i++){
int digit = s.charAt(i) - '0';
num = num * 10 + digit;
if(num > 255)
return false;
}
return true;
}
78.子集
思路: 集合中的子集,有两个思路:
1.
每个元素有选或不选两个选择
public void backTracking(int[] nums, int idx) {
if(idx==nums.length) {
result.add(new ArrayList(list));
return;
}
//选
list.add(nums[idx]);
backTracking(nums,idx+1);
//不选
list.remove(list.size()-1);
backTracking(nums,idx+1);
}
2. 收集每个结果集
public void backTracking(int[] nums, int idx) {
result.add(new ArrayList<>(list));
for(int i=idx;i<nums.length;i++) {
list.add(nums[i]);
backTracking(nums,i+1);
list.remove(list.size()-1);
}
}
90.子集II
题目链接:90. 子集 II - 力扣(LeetCode)
思路:还是先排序,一层之中用过的不能再用了,
public void backTracking(int[] nums,boolean[] used, int idx) {
result.add(new ArrayList<>(list));
for(int i=idx;i<nums.length;i++) {
if(i>0 && nums[i] == nums[i-1] && !used[nums[i]+10])continue;
list.add(nums[i]);
used[nums[i]+10] = true;
backTracking(nums,used,i+1);
list.remove(list.size()-1);
used[nums[i]+10] = false;
}
}