【leetcode】47.(Medium)PermutationsII

题目链接


解题思路:
参考

首先进行排序;
如果数组中没有重复的数字,就按照permutations的方法来做就可以了;

如果数组中有2个重复的数字,比如[1,1,3],首先将数组分为[1]和[1,3],
对[1,3]进行全排列有[1,3]和[3,1],在所有子全排列中的对应重复数字的后面添加数字即可,
比如我还需要添加1,第一个子全排列[1,3]的对应重复数字为1,1在第0位,所以我们在第1、2位分别再新添加进1,可以得到[1,1,3]和[1,3,1],
第二个子全排列[3,1]的对应重复数字1在第1位,所以我们只能在第二位添加进新的1,得到[3,1,1];

由此得到所有的全排列组合[1,1,3] [1,3,1]和[3,1,1];

如果有三个重复的数字,比如[1,1,1,3],首先将数组分为[1]和[1,1,3],通过递归可以得到[1,1,3]的全排列[1,1,3] [1,3,1] [3,1,1],
第一个全排列[1,1,3]的最后一个重复数字1在第1位(从0开始计),然后我们就在第2、3位添加新的1,得到[1,1,1,3]和[1,1,3,1]
第二个全排列[1,3,1]的最后一个重复数字1在最后一位,所以我们只能在最后一位的后面添加进新的1,得到[1,3,1,1]
对[3,1,1]进行相同的处理,可以得到[3,1,1,1]
这样就可以得到最终的所有结果了[1,1,1,3]、[1,1,3,1]、[1,3,1,1] 、 [3,1,1,1]

提交代码:

class Solution {
    public List<List<Integer>> permuteUnique(int[] nums) {
        //DP
    	List<List<Integer>> lists=new ArrayList<List<Integer>>();
    	if(nums==null||nums.length==0)	return	lists;
    	if(nums.length==1) {
    		List<Integer> list=new ArrayList<Integer>();
    		list.add(nums[0]);
    		lists.add(list);
    		return lists;
    	}
    	
    	//merge sort
    	mergeSort(nums,0,nums.length-1);
    	
    	//build subnums and calculate sublists
    	int subnums[]=new int[nums.length-1];
    	for(int i=1,j=0;i<nums.length;i++,j++) 
    		subnums[j]=nums[i];
    	
    	List<List<Integer>> sublists=permuteUnique(subnums);
    	
    	//create current lists
    	for(int i=0;i<sublists.size();i++) {  //子排列的个数
    		
    		if(nums[0]==nums[1]) {
    			int startpos=0,flag=nums[1];
    			
    			for(int pos=sublists.get(i).size()-1;pos>=0;pos--) 
    				if(sublists.get(i).get(pos)==flag){
    					startpos=pos+1;
    			        break;}

    			while(startpos<nums.length) {
    				List<Integer> list=new ArrayList<Integer>();
    				
    				for(int j=0;j<sublists.get(i).size();j++)
    				//list=sublists.get(i);  //不能直接get,不然对list的改动也会变更到sublists中去
    					list.add(sublists.get(i).get(j));
    				list.add(startpos, nums[0]);
    				
    				lists.add(list);
    				startpos++;
    			}
    		}
    		else {
    			for(int pos=0;pos<nums.length;pos++) {
    	    		List<Integer> list=new ArrayList<Integer>();

    	    		//copy the i'th sublist to list
    	    		for(int j=0;j<sublists.get(i).size();j++) 
    	    			list.add(sublists.get(i).get(j));

    	    		//list=sublists.get(i);
    	    		list.add(pos,nums[0]); 
    	    		lists.add(list);
    	    		}
    	    	}
    		}
    	return lists;
    }
    	
    

    
    public void mergeSort(int nums[],int left,int right) {
    	if(left>=right)		return;
    	
    	int mid=(left+right)/2;
    	mergeSort(nums,left,mid);
    	mergeSort(nums,mid+1,right);
    	merge(nums,left,mid,right);
    }
    
    public void merge(int nums[],int left,int mid,int right) {
    	if(left==right)		return;
    	
    	int len=right-left+1;
    	int[] tmp=new int[len];

    	int i=left,j=mid+1,k=0;
    	while(i<=mid&&j<=right) 
    		tmp[k++]=nums[i]<nums[j]?nums[i++]:nums[j++];
    	while(i<=mid)
    		tmp[k++]=nums[i++];
    	while(j<=right)
    		tmp[k++]=nums[j++];
    	
    	for(k=0;k<len;k++)
    		nums[left++]=tmp[k];
    }
    
}

运行结果:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/AXIMI/article/details/83785181