dfs递归回溯的两种体型
1. 全排列,排列型回溯
个人思路:可以枚举排列中每一个位置pos应该放什么元素,往下dfs就看看下一个位置pos放什么元素。
class Solution {
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> ansList = new ArrayList<>();
boolean[] vis = new boolean[nums.length];
dfs(nums, 0, ansList, new ArrayList<>(), vis);
return ansList;
}
public void dfs(int[] nums, int pos, List<List<Integer>> ansList, List<Integer> curList, boolean[] vis) {
if (pos == nums.length) {
ansList.add(new ArrayList<>(curList));
return;
}
for (int i = 0; i < nums.length; i++) {
if (!vis[i]) {
curList.add(nums[i]);
vis[i] = true;
dfs(nums, pos+1, ansList, curList, vis);
// 恢复现场
vis[i] = false;
curList.remove(curList.size()-1);
}
}
}
}
2. 组合,组合型回溯
个人思路:不像前面的全排列,按排列的位置应该放什么元素这种思路,而是直接看看nums中的每个元素是选还是不选,往下dfs的话就看看下一个nums的元素是选还是不选。
class Solution {
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> ansList = new ArrayList<>();
dfs(nums, 0, new ArrayList<>(), ansList);
return ansList;
}
public void dfs(int[] nums, int curI, List<Integer> curList, List<List<Integer>> ansList) {
// 递归出口
if (curI >= nums.length) {
ansList.add(new ArrayList(curList));
return;
}
// 选nums[curI]
curList.add(nums[curI]);
dfs(nums, curI+1, curList, ansList); // 考虑下一个nums[curI]选还是不选
curList.remove(curList.size()-1); // 恢复现场
// 不选nums[curI]
dfs(nums, curI+1, curList, ansList); // 考虑下一个nums[curI]选还是不选
}
}