回溯经典例题。
通过回溯生成所有可能的排列。每次递归时,选择一个数字,直到选满所有数字,然后记录当前排列,回到上层时移除最后选的数字并继续选择其他未选的数字。每次递归时,在 path
中添加一个新的数字,直到 path
的长度等于数组 nums
的长度,此时可以将 path
添加到结果集中。当递归深入到某一层时,我们在返回上层前移除 path
中最后添加的数字,恢复现场,尝试其他未选的数字。用循环遍历,然后每次把已加过的数做剔除去选。
记住,dfs递归时会逐层进入,即进入后遇到dfs便会进入下一个dfs,逐渐挖到最深层,然后在出口处加入结果集。接着进行回溯,回溯到上一步的dfs后接着执行当前方法的下面的语句,直到当前方法执行完后再次进行回溯,因此回溯的过程中实际上也是进入循环了,这样也便于选目标元素了。然后递归一定要记得加入的是path副本,回溯时要做好恢复。
java
class Solution {
public List<List<Integer>> permute(int[] nums) {
LinkedList<List<Integer>> res = new LinkedList<>(); //排列组合结果
LinkedList<Integer> path = new LinkedList<>(); //单个排列
dfs(res,nums,path);
return res;
}
public void dfs(List<List<Integer>> res, int[] nums, LinkedList<Integer> path){
if(path.size() == nums.length){
res.add( new ArrayList<Integer>(path) ); //对于每次添加的单个排列,应该都是不同的引用对象
}
for(int i=0; i<nums.length; i++){
if(path.contains(nums[i])) {continue;} //当前层中,已添加的数不再考虑
path.add(nums[i]); //未添加的数则存放
dfs(res, nums, path); //进入下一层(递归)
path.removeLast(); //从深层节点向浅层节点回溯
}
}
}