无重复全排列的理解与实现

本文详细介绍了无重复全排列的概念,并通过递归算法展示了JavaScript和Java两种语言的实现方式。解题思路从一个数到多个数的全排列递归过程清晰阐述,代码中包含关键的数组交换操作。最后,提供了完整的代码示例以供参考。
摘要由CSDN通过智能技术生成

无重复全排列的理解与实现

先直接上题目

解题思路:

以递归算法来实现可以考虑按下面的思路:
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);
	};
}


思路参考文章:
https://my.oschina.net/aminqiao/blog/263413

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值