题目:
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]
.
给定一个数组,求这个数组中给的所有元素的全排列。此题是典型的数学题,那么如何来做呢?网上找了一篇博客,关于如何编程实现全排列的。
设一组数p = {r1, r2, r3, ... ,rn}, 全排列为perm(p),pn = p - {rn}。
因此perm(p) = r1perm(p1), r2perm(p2), r3perm(p3), ... , rnperm(pn)。当n = 1时perm(p} = r1。
那么具体到做法就是采用递归的方法,首先是第一个元素与后面的元素交换,然后将这个数组分成两部分,第一部分是第一个元素,第二部分就是除第一个元素外的其他所有元素,那么对第二部分继续调用递归来做全排列;以此类推,记得最后要将第一个元素和后面交换的元素给交换回来,否则在递归的时候会将原来的数组给弄乱的。
public class Solution
{
List<List<Integer>> list = new ArrayList<List<Integer>>();
public List<List<Integer>> permute(int[] nums)
{
int length = nums.length;
if(nums == null || length == 0)
return list;
arrange(nums,0,length - 1);
return list;
}
public void swap(int[] nums,int a,int b)
{
int temp = nums[a];
nums[a] = nums[b];
nums[b] = temp;
}
public void arrange(int[] nums,int start,int end)
{
if(start == end)
{
List<Integer> l = new ArrayList<Integer>();
for(int i = 0; i < nums.length; i++)
l.add(nums[i]);
list.add(l);
}
else
{
for(int i = start; i <= end; i++)
{
swap(nums,start,i);
System.out.print(nums[start] + " " + nums[i]);
arrange(nums,start + 1,end);
swap(nums,start,i); //恢复成原来的数组,必须要有
System.out.println();
}
}
}
}
原理:
关键的就是arrange方法的else里面的内容,我的理解是(以求str[] = {"a","b","c"}的排列为例子):
用i从str[st]做一遍循环:
每一次循环中,都要将str[i]与str[i]互相调换位置:第一次开始,"a"与自己换,这时候,递归调用arrange[str,st + 1, len]
这是在求取str[str...len - 1]的排列即"b","c"的排列;
第二次,"a"与"b"互相调换,递归调用arrange[str,str + 1, len]就是在求取{"a","c"}的排列。
第三次,"a"与"c"互相调换,递归调用arrange[str, str + 1,len]就是在求取"{"b","a}的排列。
下面再以"b","c"的排列求取为例:
首先还是做循环,第一次,"b"与自己调换,这时候,调用arrange[str,st + 1,len], 就是求c的排列。呵呵,这时候终于到了函数递归调用的出口了
: st = len - 1。输出"b" "c";
第二次,类似的,输出"c","b";
至此,"b" "c"的排列求取完毕。加上前面的a,就输出"a""b""c" "a""c""b"。
类似的,就可以输出所有的排列了。