题目原文:
Given a collection of distinct numbers, return all possible permutations.
For example,
[1,2,3] have the following permutations:
[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], and [3,2,1].
题目大意:
给一个没有重复数字的数组,求所有可能的排列情况。
题目分析:
使用backtrack(List<List<Integer>> list,List<Integer> sublist,int[] nums,boolean[] visited,int visitCount)
函数递归分析,其中第一个参数是要返回的数组,第二个参数sublist记录当前搜索情况(即搜索树的路径),nums是输入的数组,visited记录了原数组中哪个数已经加入了搜索树,visitCount记录了visited数组中false的个数。如果为0说明所有数都访问过了,就把sublist加入list。其实也可以省略这个变量,而用sublist的长度和nums的长度去比,但每次都调用STL库函数会变慢。
此处需要注意的是,visitCount=0时把当前子列加入list不能写list.add(sublist);
因为加入的是sublist这个对象的引用,而再次搜索的时候改变sublist的值会导致已经加入的结果修改。所以必须写list.add(new ArrayList<Integer>(sublist));
构造一个和sublist内容相等但不同引用的数组。
源码:(language:java)
public class Solution {
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> list=new ArrayList<List<Integer>>();
boolean[] visited = new boolean[nums.length];
backtrack(list,new ArrayList<Integer>(),nums,visited,nums.length);
return list;
}
private void backtrack(List<List<Integer>> list,List<Integer> sublist,int[] nums,boolean[] visited,int visitCount)
{
if(visitCount == 0)
list.add(new ArrayList<Integer>(sublist));
else
{
for(int i=0;i<nums.length;i++) {
if(visited[i] == false) {
visited[i] = true;
sublist.add(nums[i]);
backtrack(list,sublist,nums,visited,visitCount-1);
sublist.remove(sublist.size()-1);
visited[i] = false;
}
}
}
}
}
成绩:
3ms,beats 67.81%,众数4ms,33.12%
Cmershen的碎碎念:
在大一学习计导课的时候,回溯法讲了三道例题,分别是排列数(即本题),马踏棋盘,八皇后。当时觉得八皇后很难,甚至当时的同学们之间把能不能独立写出八皇后代码看做衡量编程水平的分水岭,当然这道题现在对我来说也很难(毕竟N皇后问题在leetcode里面是hard)。排列数作为回溯法里面最基本的一道题,但也体现了回溯法最基本的要领:(1)循环+递归;(2)记录下当前搜索信息之后再递归向下搜索,搜完之后把信息删除掉,否则每次调用backtrack的时候不能维持【当前】搜索信息。