Subsets II

描述

Given a collection of integers that might contain duplicates, S, return all possible subsets.

Note:

Elements in a subset must be in non-descending order.The solution set must not contain duplicate subsets.For example,If S = [1,2,2], a solution is:

  1. [
  2. [2],
  3. [1],
  4. [1,2,2],
  5. [2,2],
  6. [1,2],
  7. []
  8. ]

分析

这题有重复元素,但本质上,跟上一题很类似,上一题中元素没有重复,相当于每个元素只能选0或1次,这里扩充到了每个元素可以选0到若干次而已。

递归

增量构造法

  1. // Subsets II
  2. // 增量构造法,版本1,时间复杂度O(2^n),空间复杂度O(n)
  3. class Solution {
  4. public:
  5. vector<vector<int> > subsetsWithDup(vector<int> &S) {
  6. sort(S.begin(), S.end()); // 必须排序
  7. vector<vector<int> > result;
  8. vector<int> path;
  9. dfs(S, S.begin(), path, result);
  10. return result;
  11. }
  12. private:
  13. static void dfs(const vector<int> &S, vector<int>::iterator start,
  14. vector<int> &path, vector<vector<int> > &result) {
  15. result.push_back(path);
  16. for (auto i = start; i < S.end(); i++) {
  17. if (i != start && *i == *(i-1)) continue;
  18. path.push_back(*i);
  19. dfs(S, i + 1, path, result);
  20. path.pop_back();
  21. }
  22. }
  23. };
  1. // Subsets II
  2. // 增量构造法,版本2,时间复杂度O(2^n),空间复杂度O(n)
  3. class Solution {
  4. public:
  5. vector<vector<int> > subsetsWithDup(vector<int> &nums) {
  6. vector<vector<int> > result;
  7. sort(nums.begin(), nums.end()); // 必须排序
  8. unordered_map<int, int> count_map; // 记录每个元素的出现次数
  9. for (int i : nums) {
  10. if (count_map.find(i) != count_map.end())
  11. count_map[i]++;
  12. else
  13. count_map[i] = 1;
  14. }
  15. // 将map里的pair拷贝到一个vector里
  16. vector<pair<int, int> > elems;
  17. for (auto p : count_map) {
  18. elems.push_back(p);
  19. }
  20. sort(elems.begin(), elems.end());
  21. vector<int> path; // 中间结果
  22. dfs(elems, 0, path, result);
  23. return result;
  24. }
  25. private:
  26. static void dfs(const vector<pair<int, int> > &elems,
  27. size_t step, vector<int> &path, vector<vector<int> > &result) {
  28. if (step == elems.size()) {
  29. result.push_back(path);
  30. return;
  31. }
  32. for (int i = 0; i <= elems[step].second; i++) {
  33. for (int j = 0; j < i; ++j) {
  34. path.push_back(elems[step].first);
  35. }
  36. dfs(elems, step + 1, path, result);
  37. for (int j = 0; j < i; ++j) {
  38. path.pop_back();
  39. }
  40. }
  41. }
  42. };

位向量法

  1. // Subsets II
  2. // 位向量法,时间复杂度O(2^n),空间复杂度O(n)
  3. class Solution {
  4. public:
  5. vector<vector<int> > subsetsWithDup(vector<int> &nums) {
  6. vector<vector<int> > result; // 必须排序
  7. sort(nums.begin(), nums.end());
  8. // 记录每个元素的出现次数
  9. unordered_map<int, int> count_map;
  10. for (int i : nums) {
  11. if (count_map.find(i) != count_map.end())
  12. count_map[i]++;
  13. else
  14. count_map[i] = 1;
  15. }
  16. // 将map里的pair拷贝到一个vector里
  17. vector<pair<int, int> > counters;
  18. for (auto p : count_map) {
  19. counters.push_back(p);
  20. }
  21. sort(counters.begin(), counters.end());
  22. // 每个元素选择了多少个
  23. unordered_map<int, int> selected;
  24. for (auto p : counters) {
  25. selected[p.first] = 0;
  26. }
  27. dfs(nums, counters, selected, 0, result);
  28. return result;
  29. }
  30. private:
  31. static void dfs(const vector<int> &S, const vector<pair<int, int> >& counters,
  32. unordered_map<int, int>& selected, size_t step, vector<vector<int> > &result) {
  33. if (step == counters.size()) {
  34. vector<int> subset;
  35. for (auto p : counters) {
  36. for (int i = 0; i < selected[p.first]; ++i) {
  37. subset.push_back(p.first);
  38. }
  39. }
  40. result.push_back(subset);
  41. return;
  42. }
  43. for (int i = 0; i <= counters[step].second; i++) {
  44. selected[counters[step].first] = i;
  45. dfs(S, counters, selected, step + 1, result);
  46. }
  47. }
  48. };

迭代

增量构造法

  1. // Subsets II
  2. // 增量构造法
  3. // 时间复杂度O(2^n),空间复杂度O(1)
  4. class Solution {
  5. public:
  6. vector<vector<int> > subsetsWithDup(vector<int> &S) {
  7. sort(S.begin(), S.end()); // 必须排序
  8. vector<vector<int> > result(1);
  9. size_t previous_size = 0;
  10. for (size_t i = 0; i < S.size(); ++i) {
  11. const size_t size = result.size();
  12. for (size_t j = 0; j < size; ++j) {
  13. if (i == 0 || S[i] != S[i-1] || j >= previous_size) {
  14. result.push_back(result[j]);
  15. result.back().push_back(S[i]);
  16. }
  17. }
  18. previous_size = size;
  19. }
  20. return result;
  21. }
  22. };

二进制法

  1. // Subsets II
  2. // 二进制法,时间复杂度O(2^n),空间复杂度O(1)
  3. class Solution {
  4. public:
  5. vector<vector<int> > subsetsWithDup(vector<int> &S) {
  6. sort(S.begin(), S.end()); // 必须排序
  7. // 用 set 去重,不能用 unordered_set,因为输出要求有序
  8. set<vector<int> > result;
  9. const size_t n = S.size();
  10. vector<int> v;
  11. for (size_t i = 0; i < 1U << n; ++i) {
  12. for (size_t j = 0; j < n; ++j) {
  13. if (i & 1 << j)
  14. v.push_back(S[j]);
  15. }
  16. result.insert(v);
  17. v.clear();
  18. }
  19. vector<vector<int> > real_result;
  20. copy(result.begin(), result.end(), back_inserter(real_result));
  21. return real_result;
  22. }
  23. };

相关题目

原文: https://soulmachine.gitbooks.io/algorithm-essentials/content/cpp/brute-force/subsets-ii.html