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]
.
分析:
采用从nums[0..i-1]递推出nums[0..i]的排列 个数变成了原来的(i+1)倍. 比如,之前nums中的元素是[1,2,3],进行排列的时候我们可以先得到前两个的为[1,2]和[2,1]. 当再加入元素3的时候,针对[1,2]这个排列3有三个空可以插进去变成[3,1,2],[1,3,2]和[1,2,3]. 对[2,1]同理可变成[3,2,1],[2,3,1]和[2,1,3].
/**
* 采用从nums[0..i-1]递推出nums[0..i]的排列 个数变成了原来的(i+1)倍.
* 比如,之前nums中的元素是[1,2,3],进行排列的时候我们可以先得到前两个的为[1,2]和[2,1].
* 当再加入元素3的时候,针对[1,2]这个排列3有三个空可以插进去变成[3,1,2],[1,3,2]和[1,2,3].
* 对[2,1]同理可变成[3,2,1],[2,3,1]和[2,1,3]
*/
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> list = new ArrayList();
List<List<Integer>> tempList = new ArrayList();//临时存储的元素
int len = nums.length;
if(len<=0){
return list;
}
/*初始化list中只有一个元素的情况*/
ArrayList<Integer> list1 = new ArrayList<Integer>();//表示外层list的一个元素
list1.add(nums[0]);
list.add(list1);
/*进入循环从nums[0..i-1]递推出nums[0..i]的排列*/
for(int i=1;i<len;i++){
int size = list.size();//i-1的时候排列的集合个数,相当于nums = [1,2,3],只排列了前两个时得到的[[1,2][2,1]]的长度
for(int j=0;j<size;j++){
list1 = (ArrayList<Integer>) list.get(j);//取出i-1的一个集合,相当于取出[[1,2][2,1]]中的[1,2]
int size1 = list1.size();
for(int k=0;k<=size1;k++){//找nums[i]可以插进去的位置
ArrayList<Integer> list2 = new ArrayList<Integer>();
list2.addAll(list1.subList(0, k));
list2.add(nums[i]);
list2.addAll(list1.subList(k, size1));
tempList.add(list2);
}
}
/*list首先把之前的元素都清空,然后全部装上最新的元素*/
list.clear();
list.addAll(tempList);
tempList.clear();
}
return list;
}
方法二:
采用全排列的思想做。求全排列的过程就是把数字与其后面的数字相交换的过程。
IList<IList<int>> result = new List<IList<int>>();
public IList<IList<int>> Permute(int[] nums)
{
if (nums.Length > 0)
{
Permutation(nums, 0);
}
return result;
}
/*
* nums 表示待排序的字符数组
* beginIndex表示开始全排列的下标
*/
public void Permutation(int[] nums, int beginIndex){
int len = nums.Length;
/*
* 说明排序到了最后一个字符,则可以把目前的字符数组转化为字符串加入到最后的结果中
* 这也是终止递归的条件。
*/
if (beginIndex == len - 1)
{
IList<int> list = new List<int>(nums);
result.Add(list);
return;
}
/*
* 如果当前开始排序的字符不是最后一个字符,则
* 1.把这个字符与其后面的所有字符位置相互换;
* 2.然后递归为开始全排列的下标为beginIndex+1;
* 3.最后要把第一步中交换的两个字符拿回来,保证charArr还是初始的待排序的字符数组。
*
*/
else {
//index对应的字符表示需要与beginIndex对应的下标交换的字符
/* 1.把这个字符与其后面的所有字符位置相互换;*/
for (int index = beginIndex; index < len;index++)
{
Swap(nums,beginIndex,index);
/*2.然后递归为开始全排列的下标为beginIndex+1;*/
Permutation(nums, beginIndex+1);
/*3.最后要把第一步中交换的两个字符拿回来,保证nums还是初始的待排序的字符数组。*/
Swap(nums,beginIndex,index);
}
}
}
private void Swap(int[] nums, int i, int j){
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}