题目:
Given a collection of integers that might contain duplicates, nums, return all possible subsets (the power set).
Note: The solution set must not contain duplicate subsets.
For example,
If nums = [1,2,2]
, a solution is:
[ [2], [1], [1,2,2], [2,2], [1,2], [] ]题意解析:
这道题目是让我们输出一个集合所有的子集,包括空集和它本身。可采用如下的算法来实现:
令输入nums = 【1,2,2】,用vector<vector<int> > res来存储结果。
按顺序遍历整个集合:
第一步res为空,将{1}加入res中,现在res中有{{1}}
第二步,复制res中所有的集合,此时res = { {1} ,{1}},将新元素2加入到所复制的新集合中,此时res = { {1},{1,2}},再将新元素2自己作为一个子集加入到res中,第二步结束后,res变为 { {1},{1,2},{2}}
第三步,重复第二步的操作,复制res中所有的集合,此时res变为{ {1},{1,2},{2},{1},{1,2},{2} },将新元素2加入其中新复制的集合,注意这里要检查重复,在子集{1}中加入2得到{1,2}和已有的子集{1,2}重复,故这时要舍弃该复制的结合,第三步结束后,res = {{1},{1,2},{2},{1,2,2},{2,2}}
第四步,nums已遍历完毕,加入空集即可得到答案。
一种c++的实现方式如下:
#include<iostream>
#include<vector>
using namespace std;
class Solution {
public:
vector<vector<int> > subsetsWithDup(vector<int>& nums) {
vector<vector<int> > res;
int n = nums.size();
int res_num = 0;
for(int i = 0; i < nums.size(); i++) {
//new_count用来记录有多少个成功的合被复制
int new_count = 0;
for(int j = 0; j < res_num; j++) {
vector<int> temp;
copy(temp,res[j]);
temp.push_back(nums[i]);
if(!is_dup(res,temp)) {
res.push_back(temp);
new_count++;
}
}
//用来记录复制次数
res_num = res_num + new_count;
vector<int> temp;
temp.push_back(nums[i]);
if(!is_dup(res,temp)) {
res.push_back(temp);
res_num = res_num+1;
}
}
vector<int> temp;
res.push_back(temp);
return res;
}
void print(vector<int> v) {
for(int i = 0; i < v.size(); i++) {
cout<<v[i]<<" ";
}
cout<<endl;
}
//集合复制
void copy(vector<int> &v1, vector<int> &v2) {
for(int i = 0; i < v2.size(); i++) {
v1.push_back(v2[i]);
}
}
//检查集合重复,就是判断两个集合是否相等
bool is_dup(vector<vector<int> > v1, vector<int> v2) {
sort(v2.begin(),v2.end());
for(int i = 0; i < v1.size(); i++) {
sort(v1[i].begin(),v1[i].end());
if(v1[i] == v2) return true;
}
return false;
}
};