Permutations

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;
			
	}

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值