回溯模板:
backtrack() {
if(终止) {
放入结果集合;
return;
}
for(本层集合中元素) {
处理节点;
backtrack();//递归
回溯,恢复现场;
}
}
491.递增子序列
题目链接:. - 力扣(LeetCode)
思路: 要找集合中不同的递增子序列,首先要排好序(从小到达),然后横向for循环遍历,纵向递归,有特殊情况,集合中是可以有重复元素的,所以同一层递归函数内的用过的数不能再用,而恢复现场那个写法是这一条递归的树枝上不能重复使用
public void backTracking(int[] nums,int start) {
if(list.size() >= 2)
result.add(new ArrayList<>(list));
HashSet<Integer> hs = new HashSet<>();
for(int i=start;i<nums.length;i++) {
if(!list.isEmpty() && nums[i]<list.get(list.size()-1) || hs.contains(nums[i])) continue;
list.add(nums[i]);
hs.add(nums[i]);
backTracking(nums,i+1);
list.remove(list.size()-1);
}
}
private void backtracking (int[] nums, int start) {
if (list.size() > 1) {
result.add(new ArrayList<>(list));
}
int[] used = new int[201];
for (int i = start; i < nums.length; i++) {
if (!list.isEmpty() && nums[i] < list.get(list.size() - 1) ||
(used[nums[i] + 100] == 1)) continue;
used[nums[i] + 100] = 1;
list.add(nums[i]);
backtracking(nums, i + 1);
list.remove(list.size() - 1);
}
}
46.全排列
题目链接:. - 力扣(LeetCode)
思路: 全排列就是一条递归的树枝上不能用用过的数
public void backTracking(int[] nums,boolean[] used) {
if(list.size() == nums.length) {
result.add(new ArrayList<>(list));
return;
}
for(int i=0;i<nums.length;i++) {
if(!used[nums[i]+10]) {
list.add(nums[i]);
used[nums[i]+10] = true;
backTracking(nums,used);
list.remove(list.size()-1);
used[nums[i]+10] = false;
}else {
continue;
}
}
}
47.全排列 II
题目链接:47. 全排列 II - 力扣(LeetCode)
思路:集合中的数可能重复,那么就在同一层上做手脚
public void backTracking(int[] nums,boolean[] used) {
if(list.size() == nums.length) {
result.add(new ArrayList<>(list));
return;
}
HashSet<Integer> hs = new HashSet<>();
for(int i=0;i<nums.length;i++) {
if(hs.contains(nums[i]) || used[i])continue;
list.add(nums[i]);
hs.add(nums[i]);
used[i] = true;
backTracking(nums,used);
list.remove(list.size()-1);
used[i] = false;
}
}