这两道题是同一类型的题目,有着相同的规律,子集II在I的基础上加了一些判断条件
题目描述:
78.子集
给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明:解集不能包含重复的子集。
示例:
输入: nums = [1,2,3]
输出:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
这道题的答案有这样的规律:
每次遍历到nums中的一个元素 i 之后,就把解集中现存所有解的末尾加上该元素 i ,构成新的解向量,加入到解集中去,解向量的总数是2 ^ n。
比如当前解集中存在
[
[],
[1]
]
时,下一个遍历到的元素是2,那么插入之后的解集如下:
[
[],
[1],
[2],
[1, 2]
]
下一个元素是3,那么插入后的解集如下:
[
[],
[1],
[2],
[1, 2],
[3],
[1,3],
[2,3],
[1, 2,3]
]
代码:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> res(1);
if(nums.empty())
return res;
for(int i = 0; i < nums.size(); i++){
int len = res.size();
for(int j = 0; j < len; j++){
vector<int> temp = res[j];
temp.push_back(nums[i]);
res.push_back(temp);
}
}
return res;
}
90. 子集II
给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明:解集不能包含重复的子集。
示例:
输入: [1,2,2]
输出:
[
[2],
[1],
[1,2,2],
[2,2],
[1,2],
[]
]
这道题与上道题最大的区别在于数组有重复元素,而且解集要去重。如果按照上题的思路,遍历过1,2后,解集如下
[
[],
[1],
[2],
[1, 2]
]
再次插入2后,将会产生这样的解向量,[2],[1,2],[2,2],[1,2,2],造成重复,但是,如果从解向量[2],开始和2搭配,新的解向量就会是[2,2],[1,2,2],刚好去除了重复值
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> res(1);
if(nums.empty())
return res;
sort(nums.begin(), nums.end());
int diff = 0;
for(int i = 0; i < nums.size(); i++){
int len = res.size();
//和上一个元素重复
if(i > 0 && nums[i - 1] == nums[i]){
for(int j = len - diff; j < len; j++){
vector<int> temp = res[j];
temp.push_back(nums[i]);
res.push_back(temp);
}
} else {
for (int j = 0; j < len; j++) {
vector<int> temp = res[j];
temp.push_back(nums[i]);
res.push_back(temp);
}
}
//计算差值
diff = res.size() - len;
}
return res;
}