题目:给定一个 没有重复数字的序列,返回其所有可能的全排列。
示例:
输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
分析:
求给定一组数的全排列,也就是排列组合问题,所以属于Backtracking(回溯)问题,通过DFS解决,只不过需要注意的是,我们一般使用DFS的时候都会设置一个访问标记的数组,用于保证深度递归的过程中,某一个元素不会被重复访问,但是由于现在我们要求的是排列组合问题,所以我们要尽可能的把所有的解求出来,那么只要一条递归路径中有一个元素不同,那就是不用的递归路径,所以当我们从一个元素递归返回的时候,要将此元素对应于访问标记数组中的值复位,保证从其他路径路过此元素时,能够正常的访问。
其实对于一组数来说,假设一共有n个数,那么这n个数全排列的结果是n!个,其具体的计算结果是 n * (n-1) * ……* 2 * 1 。我们可以将这个计算过程想象成我们使用DFS搜索时进行搜索的过程,比如最开始的时候,我们从哪个元素最先开始搜索,此时一共有n个数未被访问,那么就有n种选择;然后继续搜索,那么还剩n-1个数未被访问,此时可选择走的方向就有n-1个选择;……,以此类推,就是求所有的排列的过程。每到一个元素,进行的下一步走向的选择,就是通过for循环实现,保证所有的可能都要经历。
代码实现:
private List<List<Integer>> reslist;
public List<List<Integer>> permute(int[] nums) {
if (nums.length == 0 || nums == null){
return new ArrayList<>();
}
int n = nums.length;
boolean[] isVisited = new boolean[n];
reslist = new ArrayList<List<Integer>>();
List<Integer> sortres = new ArrayList<>();
for (int i = 0; i < nums.length; i++) {
findAllSort(nums,i,isVisited,sortres);
}
return reslist;
}
private void findAllSort(int[] nums, int i, boolean[] isVisited, List<Integer> sortres) {
if (isVisited[i]){
return;
}
isVisited[i] = true;
sortres.add(nums[i]);
if (sortres.size() == nums.length){
reslist.add(new ArrayList<>(sortres));
isVisited[i] = false;
sortres.remove(sortres.size()-1);
return;
}
for (int i1 = 0; i1 < isVisited.length; i1++) {
if (!isVisited[i1]){
findAllSort(nums,i1,isVisited,sortres);
}
}
isVisited[i] = false;
sortres.remove(sortres.size()-1);
}
记住,当遍历完一条路径的时候,给此路径添加到结果列表,需要新建一个list对象,然后将sortres结果传进去,直接将sortres添加到结果列表中是不行的,因为当我们再一次修改sortlist时,原先存于结果列表的内容也会被修改。
上面是我自己实现的代码,然后也参考了cyc2018的代码,他的代码比我的性能要好一些,但是我俩的做法思想基本是一样的:
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> permutes = new ArrayList<>();
List<Integer> permuteList = new ArrayList<>();
boolean[] hasVisited = new boolean[nums.length];
backtracking(permuteList, permutes, hasVisited, nums);
return permutes;
}
private void backtracking(List<Integer> permuteList, List<List<Integer>> permutes, boolean[] visited, final int[] nums) {
if (permuteList.size() == nums.length) {
permutes.add(new ArrayList<>(permuteList)); // 重新构造一个 List
return;
}
for (int i = 0; i < visited.length; i++) {
if (visited[i]) {
continue;
}
visited[i] = true;
permuteList.add(nums[i]);
backtracking(permuteList, permutes, visited, nums);
permuteList.remove(permuteList.size() - 1);
visited[i] = false;
}
}
参考:cyc2018