文章目录
1. 全排列(LC46)
题目描述

解题思路
定义全局变量int[][] ret记录结果,int[] path记录路径。利用决策树来辅助:

定义全局变量boolean[] check判断数组中的元素是否被使用过
- 把数组中所有元素枚举一遍,调用
check判断,如果使用过则直接排除(剪枝);没有被使用过则添加到path中。 - 回溯:函数调用完,要把
path的最后一个元素删去,并且在check中标记为false,"恢复现场" - 递归出口:遇到"叶子节点"直接返回。
代码实现
java
class Solution {
List<List<Integer>> ret = new ArrayList<>();
List<Integer> path = new ArrayList<>();
boolean[] check;
public List<List<Integer>> permute(int[] nums) {
check = new boolean[nums.length];
dfs(nums);
return ret;
}
void dfs(int[] nums){
if(nums.length == path.size()){
ret.add(new ArrayList<>(path));
return;
}
for(int i = 0;i<nums.length;i++){
if(check[i])
continue;
path.add(nums[i]);
check[i] = true;
dfs(nums);
//回溯 -》 恢复现场
path.removeLast();
check[i] = false;
}
}
}
注意:
ret.add(new ArrayList<>(path))不可以写成ret.add(path),因为第二种方式添加的是引用。当回溯path清空,ret中的内容也会清空。必须新建一个ArrayList对象
2. 子集(LC78)
题目描述

解题思路
与上一题相同,定义全局变量path记录路径,全局变量ret记录结果。
-
解法一:

- 借助决策树来判断:每一个节点可以选择数组中的元素是否存在。
- 函数头:
void dfs(int nums[],int i)i表示当前要考虑数组中第i个元素是否要存在。- 不选:直接继续调用
dfs(nums,i+1); - 选择当前元素:
path先添加当前元素,再调用dfs(nums,i+1);
- 不选:直接继续调用
- 递归出口:当
i==nums.length-1,说明已经遍历完所有元素,就可以退出了。
-
解法二:

- 第一层考虑一个元素,第二层考虑两个元素,以此类推。
- 往后扩展时只能从当前元素后面选择,否则会重复。决策树的节点就是结果。
- 函数头:
void dfs(int[] nums,int i)i 表示当前函数从第i个元素开始枚举
代码实现
- 解法一:
java
class Solution {
List<List<Integer>> ret = new ArrayList<>();
List<Integer> path = new ArrayList<>();
public List<List<Integer>> subsets(int[] nums) {
dfs(nums,0);
return ret;
}
void dfs(int[] nums,int i){
if(i == nums.length){
ret.add(new ArrayList(path));
return;
}
//不选当前元素
dfs(nums,i+1);
//选择当前元素
path.add(nums[i]);
dfs(nums,i+1);
//恢复现场
path.removeLast();
}
}
- 解法二:
java
class Solution {
List<List<Integer>> ret = new ArrayList<>();
List<Integer> path = new ArrayList<>();
public List<List<Integer>> subsets(int[] nums) {
dfs(nums,0);
return ret;
}
void dfs(int[] nums,int i){
//每一个节点都是一个结果
ret.add(new ArrayList<>(path));
for(int j = i;j<nums.length;j++){
path.add(nums[j]);
dfs(nums,j+1);
//恢复现场
path.removeLast();
}
}
}