Given a collection of numbers that might contain duplicates, return all possible unique permutations.
For example,
[1,1,2]
have the following unique permutations:
[1,1,2]
, [1,2,1]
, and [2,1,1]
.
Subscribe to see which companies asked this question
思路:
承接上一题【LeetCode:Permutations】
由于全排列就是从第一个数字起每个数分别与它后面的数字交换。我们先尝试加个这样的判断——如果一个数与后面的数字相同那么这二个数就不交换了。如122,第一个数与后面交换得212、221。然后122中第二数就不用与第三个数交换了,但对212,它第二个数与第三个数是不相同的,交换之后得到221。与由122中第一个数与第三个数交换所得的221重复了。所以这个方法不行。
换种思维,对122,第一个数1与第二个数2交换得到212,然后考虑第一个数1与第三个数2交换,此时由于第三个数等于第二个数,所以第一个数不再与第三个数交换。再考虑212,它的第二个数与第三个数交换可以得到解决221。此时全排列生成完毕。
这样我们也得到了在全排列中去掉重复的规则——去重的全排列就是从第一个数字起每个数分别与它后面非重复出现的数字交换。
java code:
public class Solution { public List<List<Integer>> permuteUnique(int[] nums) { List<List<Integer>> res = new ArrayList<List<Integer>>(); permute(res, nums, 0); return res; } // 自定义函数 void permuteUnique(List<List<Integer>> res, int[] nums, int pos) { if(pos == nums.length) { ArrayList<Integer> list = new ArrayList<Integer>(); for(int num:nums) list.add(num); res.add(list); return; } for(int i=pos;i<nums.length;i++){ if(isSwap(nums,pos,i)) { swap(nums, pos,i); permute(res,nums,pos+1); swap(nums, pos,i); } } } void swap(int[] nums, int i, int j) { int t = nums[i]; nums[i] = nums[j]; nums[j] = t; } boolean isSwap(int[] nums, int lo, int hi) { for(int i=lo;i<hi;i++) { if(nums[i]==nums[hi]) return false; } return true; } }