凌云的博客

行胜于言

LeetCode 算法题 47. 全排列 II

分类:algorithm| 发布时间:2016-10-13 10:35:00


题目

给定一个可包含重复数字的序列,返回所有不重复的全排列。

示例:

输入: [1,1,2]
输出:
[
  [1,1,2],
  [1,2,1],
  [2,1,1]
]

解法 1

跟上一题的解法类似,由于数字有可能重复,因此需要通过 set 来避免重复 swap 到相同的值。

class Solution {
public:
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        vector<vector<int>> ret;
        permute(nums, 0, ret);
        return ret;
    }

    void permute(vector<int>& nums, int idx, vector<vector<int>>& ret) {
        if (idx == nums.size() - 1) {
            ret.push_back(nums);
            return;
        }

        unordered_set<int> sets;
        for (int i = idx; i < nums.size(); ++i) {
            if (sets.find(nums[i]) != sets.end()) continue;
            swap(nums[idx], nums[i]);
            sets.insert(nums[idx]);
            permute(nums, idx + 1, ret);
            swap(nums[i], nums[idx]);
        }
    }
};

解法 2

class Solution {
public:
    vector<vector<int>> permuteUnique(vector<int> &nums) {
        vector<vector<int>> ret;
        vector<int> r;
        unordered_map<int, int> m;
        for (int i : nums) {
            m[i]++;
        }

        permuteUnique(m, r, nums.size(), ret);
        return ret;
    }

    void permuteUnique(unordered_map<int, int> &m, vector<int> &r, int remain, vector<vector<int>> &ret) {
        if (remain <= 0) {
            ret.push_back(r);
            return;
        }

        for (auto &p : m) {
            if (p.second <= 0) continue;
            p.second--;
            r.push_back(p.first);
            permuteUnique(m, r, remain - 1, ret);
            r.pop_back();
            p.second++;
        }
    }
};