1. 程式人生 > >【leetcode】47.(Medium)PermutationsII

【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]; } }

執行結果:
在這裡插入圖片描述