回溯
有溯本清源的意思,就是往回走寻找根源
直接找一道题来看
class Solution {
public List<List<Integer>> permute(int[] nums) {
dfs(nums, 0);
return ans;
}
List<List<Integer>> ans = new ArrayList<>();
void dfs(int[] nums, int cur) {
if (cur == nums.length) {
List<Integer> list = new ArrayList<>();
for (int i : nums) {
list.add(i);
}
ans.add(list);
return;
}
for (int i = cur; i < nums.length; i++) {
swap(nums, cur, i);
dfs(nums, cur + 1);
swap(nums, cur, i);
}
}
void swap(int[] nums, int i, int j) {
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}
通过置换数组的元素这样可以遍历每一种排列形式,并且递归回来后数组是不会变的
因为我们在递归回来后也做了一次置换,这样可以使数组回到置换前的样子,这就是回溯
回溯只是一种思想
并不是一类特定的算法
递归其实也有回溯的意思
回溯是回到原来的位置
为什么要回到原来的位置
这个问题想清楚了递归回溯都会理解
递归内部可能会调用类中的属性
如果修改类中的属性所有的递归都会受影响
八皇后
int[] rows = new int[9]
int[] cold = new int[9]
标识行和列是否被占用(已经有皇后)
递归之前你需要标识当前位置已经有皇后(后面皇后不能出现在这个列这个行)
rows[i] = 1
cols[j] = 1
这里有对角线我先不说
主要是要明白为什么回来的时候还需要
rows[i] = 0
cols[j] = 0
就是因为对下一次循环来说这个ij是未被选中的