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], [3,2,1] ]
一道比较经典的题,当时看了很多的解题思路感觉还是自己想的比较清晰,于是这两天的闲暇时间实现了这个算法。其实算法很容易,但是就是递归方面的知识点比较薄弱,所以花费了比较长的时间。
实现的思路是交换,过程可以参考下图
在函数permute(int[] nums, int index,List<List<Integer>> result) 中,index用来表示当前走到了数组的哪一位, 当index等于数组大小的-1 的时候,说明一个排序已经完成。
for(int i= index;i<nums.length;i++){
swap(nums,i, index);
permute(nums, index+1,result);
swap(nums,i, index);
}
这个函数的for循环部分,i 要从index开始走起,因为需要把自己跟自己交换的这种情况带到递归的函数中去。 前后的两个swap函数,第一swap应该比较容易理解,就是讲当前i指向的位置跟index的值交换;而第二个swap的作用是还原第一个swap做的交换。举个例子,在index =2 时,也就是递归到图中的第二层的时候,类似于深度优先搜索,会先算出[1,2,3 ] 排列下的所有情况, 然后再去计算 [2,1,3] , 然后再是[3,2,1] 排列下的所有情况。从状态[1,2,3] --> [2,1,3] --> [3,2,1]的转移过程中,需要修复在第三层对数组进行的修改操作。比如说第二层的[1,2,3]计算出结果时,会在第三层得到一个数组:[1,3,2], 而这数组需要通过swap(2<->3)还原成[1,2,3],这样才能在第二层的for循环的时候做出正确的交换,即得到:[2,1,3],也就是第二层的第二个数组。
public class Solution {
public List<List<Integer>> permute(int[] nums) {
if(nums == null) return null;
List<List<Integer>> result = new ArrayList<List<Integer>>();
if(nums.length == 0 ){
List<Integer> list = new ArrayList<Integer>();
result.add(list);
return result;
}
permute(nums,0, result);
return result;
}
private void permute(int[] nums, int index,List<List<Integer>> result){
if(index == nums.length-1 ){
result.add(arrayToList(nums));
return;
}else{
for(int i= index;i<nums.length;i++){
swap(nums,i, index);
permute(nums, index+1,result);
swap(nums,i, index);
}
}
}
private void swap(int []nums, int i, int j){
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
private List<Integer> arrayToList(int [] nums){
List<Integer> result = new ArrayList<Integer>();
for(int i=0;i< nums.length;i++){
result.add(nums[i]);
}
return result;
}
}