1. 题目

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],
[2,1,1]
]

2. 思路

和有重复的排列的区别是对重复元素要特殊处理。即重复元素在插入时其实保持有序即可。把重复元素当做a1 a2 a3的a。
具体做法是,在插入时如果当前插入元素a是在递归子集中已经存在的元素,则新插入的位置是在已有序列的最后一个a之后的位置开始。
比如112, 12的已有集合是{12,21}, 下一个1插入时,再插入{12}时只能在2之前开始插入,得到{112,121}。{21}在插入时只能在1之后开始插入,得到{211}。

3. 代码

耗时:43ms

class Solution {
public:
    // 和非重复的类似, 但是将beg元素向已递归结果里插入时,先找到等于自己的节点的位置,从其之后然后开始插入
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        sort(nums.begin(), nums.end()); // 排序是为了方便判断当前字符是否是重复数字
        return permute(nums, 0);
    }
    vector<vector<int>> permute(vector<int>& nums, int beg) {
        int sz = nums.size();
        vector<vector<int>> ret;
        if (sz == beg) { return ret; }
        if (sz == beg + 1) {
            vector<int> one;
            one.push_back(nums[beg]);
            ret.push_back(one);
            return ret;
        }
        vector<vector<int>> subs = permute(nums, beg+1);
        // 将nums[beg]插入到subs的所有结果的所有位置,除了前一个元素等于自己的情况
        int beg_v = nums[beg];
        bool dup = sz >=2 && nums[beg+1] == nums[beg];
        for (int i = 0; i < subs.size(); i++) {
            vector<int>& vec_i = subs[i];
            int j = 0;
            if (dup) {
                j = vec_i.size() - 1;
                for (; j >= 0; j--) {
                    if (vec_i[j] == beg_v) {
                        j++;
                        break;
                    }
                }
            }
            for (; j <= vec_i.size(); j++) { // j表示插入的位置
                vector<int> cat;
                for (int k = 0; k <= vec_i.size(); k++) {
                    if (k == j) {
                        cat.push_back(beg_v);
                    } else if (k < j) {
                        cat.push_back(vec_i[k]);
                    } else {
                        cat.push_back(vec_i[k-1]);
                    }
                }
                ret.push_back(cat);
            }
        }
        return ret;
    }
};

knzeus
72 声望28 粉丝

行万里路,读万卷书