#题目:
这里主要考虑的是无重复的全排列
比如: (1,2,3) 全排列为 [1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]
#method 1 /*
- 简单地说:就是第一个数分别以后面的数进行交换
*E.g:E = (a , b , c),则 prem(E)= a.perm(b,c)+ b.perm(a,c)+ c.perm(a,b)
*然后a.perm(b,c)= ab.perm(c)+ ac.perm(b)= abc + acb.依次递归进行
*/
public ArrayList<ArrayList<Integer>> Permutation(int[] nums){
ArrayList<ArrayList<Integer>> arrs = new ArrayList<>();
ArrayList<Integer> arr = new ArrayList<>();
helper(nums,0,arr,arrs);
return arrs;
}
/*
* 简单地说:就是第一个数分别以后面的数进行交换
*E.g:E = (a , b , c),则 prem(E)= a.perm(b,c)+ b.perm(a,c)+ c.perm(a,b)
*然后a.perm(b,c)= ab.perm(c)+ ac.perm(b)= abc + acb.依次递归进行
*/
public void helper(int[] nums,int pos,ArrayList<Integer> arr,ArrayList<ArrayList<Integer>> arrs){
if(pos == nums.length){
//这是正确的写法
arr = new ArrayList<>();
for (int i = 0; i < nums.length; i++) {
arr.add(nums[i]);
}
arrs.add(arr);
//差一点点 天壤之别系列1 不正确
// for (int i = 0; i < nums.length; i++) {
// arr.add(nums[i]);
// }
// arrs.add(arr);
//差一点点 天壤之别系列2 不正确
// for (int i = 0; i < nums.length; i++) {
// arr.add(nums[i]);
// }
// arrs.add(new ArrayList<>(arr));
}else{
/**
* 我觉得过程是这样的
* perm(a,b,c) = a+perm(b,c)(pos = 0 取出a) =
*/
for (int i = pos; i < nums.length; i++) { //pos表示
swap(nums,i,pos); //pos表示当前数
helper(nums,pos+1,arr,arrs); //当前pos位置确定,在pos位置后面继续全排列
swap(nums,i,pos); //还原到原来的数组
}
}
#method 2
采用迭代的方法真是感觉想出这个方法的人 牛逼
//再提供一个更为巧妙的全排列思路
/*
* 第 1 步:
当只有1个数字1的时候,只有一种组合
1
第 2 步:
当有两个数字1、2的时候,分别把 2 放到 1 的前面和后面,就可以得到下面两个组合
2 1
1 2
第 3 步.
当有三个数字1、2、3的时候,可以针对第 2 步中得到的两个组合,把 3 分别插入这两个组合之中。
对于组合 2 1,我们可以得到下面 3 个组合:
3 2 1
2 3 1
2 1 3
对于组合 1 2,我们可以得到下面 3 个组合:
3 1 2
1 3 2
1 2 3
于是我们一共得到了 6 个组合
第 4 步:
对于四个数字1、2、3、4,按照第 3 步中的做法,将 4 分别插入在第 3 步中得到的 6 个组合,最后我们可以得到 24 个组合
可用循环表示,真是方便极了
*/
public ArrayList<ArrayList<Integer>> PermutationByRecursion(int[] nums){
ArrayList<ArrayList<Integer>> lists = new ArrayList<>();
if(nums.length<=0){
return lists;
}
ArrayList<Integer> list = new ArrayList<>();
if(nums.length>0){
list.add(nums[0]);
lists.add(list);
}
for (int i = 1; i < nums.length; i++) { //表示每次取得是第几个数
int lastSize = lists.size(); //这里避免死循环 取出上一次集合的大小
for (int j = 0; j < lastSize; j++) { //遍历上一次集合中有多少排列
for (int j2 = 0; j2 < lists.get(0).size()+1; j2++) { //取出第一个排列,依次插入新的数,组成新的排列 插入的话可以插入多一个位置
ArrayList<Integer> arr = new ArrayList<>(lists.get(0));
arr.add(j2, nums[i]);
lists.add(arr);
}
lists.remove(0); //始终移除第一个排列
}
}
return lists;
}