回溯算法
排列
List<LinkedList<Integer>> res = new LinkedList<List<Integer>>();
public void backtrack(int[] nums,LinkedList<Integer> track) {
if(track.size() == nums.length) {
res.add(new LinkedList(track));
return;
}
for (int i=0;i<nums.length;i++) {
if(track.contains(nums[i])) {
continue;
}
track.add(nums[i]);
//进入下一层决策树
backtrack(nums, track);
track.removeLast();
}
}
public List<List<Integer>> permute(int[] nums) {
List<Integer> track = new LinkedList<Integer>();
backtrack(nums,track);
return res;
}
组合
// 记录所有组合
List<List<Integer>> res = new LinkedList<List<Integer>>();
//主函数
public List<List<Integer>> combine(int n,int k){
if(k<=0 || n<=0) {
return res;
}
List<Integer> track = new LinkedList<Integer>();
backtrack(n,k,1,track);
return res;
}
//回溯模板
public void backtrack(int n,int k,int start,List<Integer> track) {
//到达叶子节点才更新res
if(track.size()==k) {
res.add(new LinkedList(track));
return;
}
//i从start开始递增
for(int i=start;i<=n;i++) {
//做选择
track.add(i);
//递归回溯
backtrack(n,k,i+1,track);
//撤销选择
track.remove(track.size()-1);
}
}
变量 track所指向的列表 在深度优先遍历的过程中只有一份 ,深度优先遍历完成以后,回到了根结点,成为空列表。
在 Java 中,参数传递是 值传递,对象类型变量在传参的过程中,复制的是变量的地址。这些地址被添加到 res 变量,但实际上指向的是同一块内存地址,因此我们会看到 66 个空的列表对象。解决的方法很简单,在 res.add(track); 这里做一次拷贝即可。
res.add(new LinkedList(track));