无重复全排列的理解与实现
先直接上题目
解题思路:
以递归算法来实现可以考虑按下面的思路:
1、一个数的全排列,如排列{1},就是这个数本身这一种情况2、两个数的全排列,如排列{1,2}:
第一步:将{1}放在第零个位置,剩下的{2}进行一个数的全排列,结果为{1,2}
第二步:将{2}放在第零个位置,剩下的{1}进行一个数的全排列,结果为{2,1}
即两个数的全排列为以上2种情况。 3、三个数的全排列,如排列{1,2,3}:
第一步:将{1}放在第零个位置,剩下的{2,3}进行两个数的全排列,结果为{1,2,3} {1,3,2}
第二步:将{2}放在第零个位置,剩下的{1,3}进行两个数的全排列,结果为{2,1,3} {2,3,1}
第三步:将{3}放在第零个位置,剩下的{1,2}进行两个数的全排列,结果为{3,1,2} {3,2,1}即三个数的全排列为以上6种情况。
4、即m个数(无重)的全排列,就是将m个数分别放在第零个位置,再将剩下的m-1个数的全排列加在后面,当m-1=1时为递归>的出口。
也就是说
以全排列是操作的是数组为例,当 N = 3的时候,数组为 [1, 2, 3]
① 把1放在 a[0] 的位置(原本也是如此,a[0] = a[0]),打印2,3的全排列(即a[1], a[2]的全排列)1 2 3 1 3 2
② 把2放在a[0]的位置(这时候需要交换原数组的a[0]和a[1]),然后打印1, 3的全排列
2 1 3 2 3 1
打印完后再换回原来的位置,即1还是恢复到a[0],2还恢复到a[1]的位置
③把3放在a[0]的位置(这时候需要交换的是原数组的a[0]和a[2]),然后打印1,2的全排列3 1 2 3 2 1
打印完后再换回原来的位置,即1还是恢复到a[0],3还恢复到a[2]的位置,至此,全排列完成,当 N = 4,5,6,……的时候,以此类推。
代码:
js实现:
用数组来实现,定义一个空数组list,每当要打印一次全排列(数组的值)就push进list里,最后输出list
/**
* @param {number[]} nums
* @return {number[][]}
*/
function swap(arr,a,b){
var temp;
temp=arr[a];
arr[a]=arr[b];
arr[b]=temp;
};
function pl(arr,n,list){
if(n==arr.length-1){
/*
注意这里存放的不能是arr,而是先用...arr展开当前数组的值,再用[]扩回一个数组
如果这里直接存放arr,for循环每一次循环改变arr时,当前存放的值也会改变,最后list里存放的就是多个一模一样的值
*/
list.push([...arr])
};
for(let i=n;i<arr.length;i++){
swap(arr,i,n);
pl(arr,n+1,list);
swap(arr,i,n);
}
};
var permute = function(nums) {
var list = [];
var arr=nums;
pl(arr,0,list);
return list;
};
java实现:
因为java数组是要明确知道有多少个元素的,所以这里用集合output来存放输入的数组nums,再定义一个空集合res,每当要打印一次全排列(output的值)就add进res里,最后输出res
class Solution {
public List<List<Integer>> permute(int[] nums) {
int []a=nums;
List<List<Integer> > res = new ArrayList<List<Integer>>();
List<Integer> output = new ArrayList<Integer>();
//先将数组的值存入集合output中,output就类似js的数组,打印时输出的值类似[1,2,3]
for(int num:a){
output.add(num);
};
px(0,output,res);
return res;
};
public static void px(int n,List<Integer> output,List<List<Integer> > res){
int temp;
if(n==output.size()-1){
/*
同样的,这里存放的不能是output,而是output当前的值。如果这里直接存放output,for循环每一次循环改变output时,当前存放的值也会改变,最后res里存放的就是多个一模一样的值
*/
res.add(new ArrayList<Integer>(output));
};
for(int i=n;i<output.size();i++){
swap(output, i, n);
px(n+1,output,res);
swap(output, i, n);
};
};
public static void swap(List<Integer> output,int i,int n){
int temp;
//利用get set方法调换集合中元素的值
temp = output.get(i);
output.set(i, output.get(n));
output.set(n,temp);
};
}