跳转至

47. Permutations II

Leetcode Backtracking

题目

Given a collection of numbers that might contain duplicates, return all possible unique permutations.

Example:

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

思路

这道题目和46. Permutations基本相同,唯一有区别的地方是排列的数字可能会重复。把结果放在set中,就可以除去重复的结果了。

public List<List<Integer>> permuteUnique(int[] nums) {
    if (nums == null || nums.length == 0) 
        return new ArrayList<List<Integer>>();
    Set<List<Integer>> list = new HashSet<>();
    LinkedList<Integer> chosen = new LinkedList<>(), 
        numbers = new LinkedList<>();
    for (int n : nums) numbers.add(n);
    permuate(list, numbers, chosen);
    return new ArrayList<List<Integer>>(list);
}

private void permuate(Set<List<Integer>> list, 
        LinkedList<Integer> nums, LinkedList<Integer> chosen) {
    // base case
    if (nums.size() == 0)  
        list.add(new ArrayList<Integer>(chosen));
    for (int i = 0; i < nums.size(); i++) {
        Integer n = nums.remove(i);
        chosen.addLast(n);                  // chosen
        permuate(list, nums, chosen);       // explore
        nums.add(i, n);                     // unchosen
        chosen.removeLast();
    }
}
class Solution {
public:
    void permuteUniqueHelper(set<vector<int>> &result, vector<int>& nums, vector<int>& chosen){
        if (nums.size()==0){
            result.insert(chosen);
        }else{
            for (vector<int>::iterator iter=nums.begin(); iter!=nums.end(); iter++){
                //choose
                int s = *iter;
                chosen.push_back(s);
                nums.erase(iter);

                //explore
                permuteUniqueHelper(result, nums, chosen);

                //unchoose
                chosen.pop_back();
                nums.insert(iter, s);
            }
        }
    }


    vector<vector<int>> permuteUnique(vector<int>& nums) {
        vector<int> chosen;
        set<vector<int>> result;
        permuteUniqueHelper(result, nums, chosen); 
        vector<vector<int>> finals(result.begin(), result.end());
        return finals;
    }
};

另一种方法是先把数组排序,遍历时直接无视重复的数字。也就是说在当前的遍历中只遍历1个重复数字,剩下的重复数字在下一层次遍历中遍历,这样恰好使每一层遍历都遍历一个重复数字。能大幅减少运行时间。

public List<List<Integer>> permuteUnique(int[] nums) {
    if (nums == null || nums.length == 0) 
        return new ArrayList<List<Integer>>();
    List<List<Integer>> list = new ArrayList<>();
    LinkedList<Integer> chosen = new LinkedList<>(), 
        numbers = new LinkedList<>();
    Arrays.sort(nums);
    for (int n : nums) numbers.add(n);
    permuate(list, numbers, chosen);
    return new ArrayList<List<Integer>>(list);
}

private void permuate(List<List<Integer>> list, 
                LinkedList<Integer> nums, LinkedList<Integer> chosen) {
    // base case
    if (nums.size() == 0)  list.add(new ArrayList<Integer>(chosen));
    for (int i = 0; i < nums.size(); i++) {
        if (i > 0 && nums.get(i) == nums.get(i - 1)) continue;
        Integer n = nums.remove(i);

        chosen.addLast(n);                  // chosen
        permuate(list, nums, chosen);       // explore
        nums.add(i, n);                     // unchosen
        chosen.removeLast();
    }
}
class Solution {
public:
    void permuteUniqueHelper(vector<vector<int>> &res, 
                vector<int>& nums, vector<int>& chosen){
        if (nums.size()==0){
            res.push_back(chosen);
        }else{
            for (vector<int>::iterator iter=nums.begin(); 
                        iter!=nums.end(); iter++){
                 //遇到重复时,直接跳过
                if  ((iter!=nums.begin()) &&((*iter)==*(iter-1))){
                } else{
                    //choose
                    int s = *iter;
                    chosen.push_back(s);
                    nums.erase(iter);
                    //explore
                    permuteUniqueHelper(res, nums, chosen);
                    //unchoose
                    chosen.pop_back();
                    nums.insert(iter, s);
                }
            }
        }
    }

    vector<vector<int>> permuteUnique(vector<int>& nums) {
        vector<int> chosen;
        vector<vector<int>> res;
        sort(nums.begin(), nums.end()); // 1. 排序
        permuteUniqueHelper(res, nums, chosen); 
        return res;
    }
};