leetcode 46. Permutations

一 题目

Given a collection of distinct integers, return all possible permutations.

Example:

Input: [1,2,3]
Output:
[
  [1,2,3],
  [1,3,2],
  [2,1,3],
  [2,3,1],
  [3,1,2],
  [3,2,1]
]

Accepted 437,979 Submissions 761,542

二 分析

求全排列。medium 级别。从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列。当m=n时所有的排列情况叫全排列。

之前做过一个题目:leetcode 31. Next Permutation 就是求全排列的下一个字典序。

我们有知道全排列就是N! 个结果。所以直接套用:

 public static List<List<Integer>> permute(int[] nums) {
	   List<List<Integer>> res = new ArrayList<>();
	   if(nums ==  null){
		   return res;
	   }
	   int count = 1;
       for(int i=1;i<=nums.length ;i++){
    	   count *=i;
       }
       while( count>0){
    	   nextPermutation(nums);
    	   List<Integer> l = new ArrayList<>();
    	   for(int i=0;i<nums.length;i++){
    		   l.add(nums[i]);
    	   }
    	   res.add(l);
    	   count --;
       }
       
	return res;
        
    }

这不是个好办法。还是回到题目本身上。

2.1 递归

  • 数字1个本身就是全排序。
  • 1跟2,就是12,21 两种
  • 1、2、3 就是 [1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 2, 1], [3, 1, 2]  即以1开头的和2、3的全排列的组合、以2开头的和1,3的全排列的组合和以3开头的和1,2的全排列的组合。

以次推理,1234全排列就是:

  1  +  234(的全排列)

  2  +  134(的全排列)

  3  +  124(的全排列)

  4   + 123 (的全排列)

    可以理解,后面每个数都跟第一个交换过。总结来说就是采用位置两两交换,交换后出现一种新的组合,将这种新的组合添加到结果集。代码如下:

 public static List<List<Integer>> permute(int[] nums) {
	   List<List<Integer>> res = new ArrayList<>();
	   helper(nums,0, res);
       
	return res;
        
    }
    //递归
   private static void helper( int[] nums, int start,List<List<Integer>>  res ){
	   if(start == nums.length-1){//到达结尾,实现全排序
		   ArrayList<Integer> list = new ArrayList<>();
	        for(int num: nums){
	            list.add(num);
	        }
	        res.add(list);
	        return;
	   }
	   // 将当前位置的数跟后面的数交换,并搜索解
	   for(int i=start;i< nums.length;i++){
		   swap(nums,i,start);//交换
		   helper(nums,start+1 ,res);
		   swap(nums,i,start);//还原
	   }
   }
	
	private static  void swap(int[] nums, int i, int j) {
	    int t = nums[i];
	    nums[i] = nums[j];
	    nums[j] = t;
	}

Runtime: 1 ms, faster than 97.68% of Java online submissions forPermutations.

Memory Usage: 37.8 MB, less than 89.36% of Java online submissions forPermutations.

时间复杂度:O(N!)

还有种递归的实现方式,grandyang大神说是CareerCup 书上的,网上也有这种介绍。又学习一个点。

这种思路是采用逐一向临时list添加元素,临时list满足条件后再加入到结果res中。

当 n=1 时,数组中只有一个数 a1,其全排列只有一种,即为 a1

当 n=2 时,数组中此时有 a1a2,其全排列有两种,a1a2 和 a2a1,那么此时考虑和上面那种情况的关系,可以发现,其实就是在 a1 的前后两个位置分别加入了 a2 

当 n=3 时,数组中有 a1a2a3,此时全排列有六种,分别为 a1a2a3, a1a3a2, a2a1a3, a2a3a1, a3a1a2, 和 a3a2a1。那么根据上面的结论,实际上是在 a1a2 和 a2a1 的基础上在不同的位置上加入 a3 而得到的。

_ a1 _ a2 _ : a3a1a2, a1a3a2, a1a2a3

_ a2 _ a1 _ : a3a2a1, a2a3a1, a2a1a

这样看起来,也是很好理解的。更简洁些

 public static List<List<Integer>> permute(int[] nums) {
	   List<List<Integer>> res = new ArrayList<>();
	   ArrayList<Integer> list = new ArrayList<>();
	   helper(nums,list, res);
       
	return res;
        
    }
   //递归2 插入法
   private static void helper( int[] nums,   ArrayList<Integer> list, List<List<Integer>>  res ){
	   if(list.size() == nums.length){//到达结尾,实现全排序	       
	        res.add(new ArrayList<>(list));
	        return;
	   }
	   for(int i=0;i<nums.length;i++){
		   //插入前先判断
		   if(!list.contains(nums[i]) ){
			   list.add(nums[i]);//插入
			   helper(nums,list,res);
			   list.remove(list.size()-1);//删除
		   }
	   }   
   }

Runtime: 1 ms, faster than 97.68% of Java online submissions forPermutations.

Memory Usage: 37.1 MB, less than 97.16% of Java online submissions forPermutations.

 

参考:

https://www.cnblogs.com/grandyang/p/4358848.html

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值