給定一個可包含重複數字的序列,返回所有不重複的全排列。
示例:
輸入: [1,1,2]
輸出:
[
[1,1,2],
[1,2,1],
[2,1,1]
]
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/permutations-ii
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。
class Solution {
List<List<Integer>> ret = new ArrayList<>();
public List<List<Integer>> permuteUnique(int[] nums) {
Arrays.sort(nums);//先排序
int[] tmp = new int[nums.length];
boolean[] vis = new boolean[nums.length];
for(int i=0 ; i<nums.length ; i++){
tmp[0] = nums[i];
vis[i] = true;
permute(nums, i ,tmp, 0, vis);
vis[i] = false;
}
return ret;
}
void permute(int[] nums, int n, int[] cur, int k, boolean[] v){
/**
這裏去重不可以單純判斷是否排序後的nums[i] == nums[i-1]
因爲這是排列,不管是不是重複,[1,1]得排成[1,1]而不是第一個[1]出現後忽略第二個[1]
評論中給了一個很好的思路,用另一個visited[]記錄上個元素是否被訪問過
因爲是按照排序的順序選擇,所以上個元素i-1一旦被選擇過,必然是在上一輪選擇,則此時選擇i沒問題
若上一個元素i-1未被選擇過,則必然是for循環分別訪問,則此時訪問i會出現重複
*/
if(n!=0 && nums[n]==nums[n-1] && !v[n-1]){//與上一個數字相等且上一個數字未被訪問過
return ;
}
if(k == cur.length-1){
List<Integer> tmp = new ArrayList<>();
for(int val:cur){
tmp.add(val);
}
ret.add(new ArrayList<Integer>(tmp));
return ;
}
for(int i=0 ; i<nums.length ; i++){
if(v[i]){
continue;
}
cur[k+1] = nums[i];
v[i] = true;
permute(nums, i ,cur , k+1, v);
v[i] = false;
}
}
}