一:subset I
题目:
Given a set of distinct integers, 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,3]
, a solution is:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
链接:https://leetcode.com/problems/subsets/
分析:说白了就是求不同元素所构成的所有子集,这里提供三种方法
(1)递归————较难理解
对结合[1,2,3] 从0结点的1开始,都有选择或者不选,不选为空,放在左子树,选择放在由子树,这样就得到一棵完全二叉树,其中叶子结点就是我们所求。理解代码可以试着从只有1个结点开始思考。
图中与代码有差异,左右刚好相反

- class Solution {
- public:
- void recursion(vector<int> temp, vector<int> &S, int level, vector<vector<int> > &result){
- if(level == S.size()){
- result.push_back(temp);
- return;
- }
- recursion(temp, S, level+1, result);
- temp.push_back(S[level]);
- recursion(temp, S, level+1, result);
- }
- vector<vector<int> > subsets(vector<int> &S) {
- sort(S.begin(), S.end());
- vector<int> temp;
- vector<vector<int> > result;
- recursion(temp, S, 0, result);
- return result;
- }
- };
(2) 迭代
通过上图我们可以看出,每次都是在原有的子集后面添加新元素S[i] 并加入到result中就会得到另外一个子集,因此可以采用迭代处理。
- class Solution {
- public:
- void iterSet(int i, vector<vector<int> > &result, vector<int> &S){
- int n = result.size();
- for(int j = 0; j < n; j++){
- vector<int> temp = result[j];
- temp.push_back(i);
- result.push_back(temp);
- }
- }
- vector<vector<int> > subsets(vector<int> &S) {
- vector<vector<int> > result;
- sort(S.begin(), S.end());
- vector<int> temp;
- result.push_back(temp);
- for(int i = 0; i < S.size(); i++){
- iterSet(S[i], result, S);
- }
- return result;
-
- }
- };
(3)位操作
对于n个元素,每个元素要么加入要么不加入,则会得到一个n位的二进制串,n为二进制串可以看做是一个状态或者说一个子集,每个元素与一位一一对应,状态的大小为1<<n. 对于每个状态j,我们通过判断第k位是否为1,为1则将S[k]加入vec,判断结束,将vec加入result即可。
- class Solution {
- public:
- vector<vector<int> > subsets(vector<int> &S) {
- vector<vector<int> > result;
- int n = S.size();
- int max = 1 << n;
- int i = 0;
- sort(S.begin(), S.end());
- while(i < max){
- int j = i;
- vector<int> temp;
-
-
-
- int index = 0;
- while(j>0){
- if(j&1) temp.push_back(S[index]);
- j = j >> 1;
- index++;
- }
- result.push_back(temp);
- i++;
- }
- return result;
-
- }
- };
二:subset 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:
[
[2],
[1],
[1,2,2],
[2,2],
[1,2],
[]
]
链接:https://leetcode.com/problems/subsets-ii/
分析:与unique paths的区别在于允许元素重复,这是当元素重复时,我们会发现每次加入的子集都是上次迭代的子集,因此需要对迭代法略做改进。
- class Solution {
- public:
- void iterSet(int i, vector<vector<int> > &result, vector<int> &S, int &t){
- int n = result.size();
- int count = 0;
- int j = 0;
- if(i-1>=0 && S[i]==S[i-1])j = n-t;
- for(;j < n; j++){
- vector<int> temp = result[j];
- temp.push_back(S[i]);
- result.push_back(temp);
- count++;
- }
- t = count;
- }
- vector<vector<int> > subsetsWithDup(vector<int> &S) {
- vector<vector<int> > result;
- sort(S.begin(), S.end());
- vector<int> temp;
- result.push_back(temp);
- int t = 0;
- for(int i = 0; i < S.size(); i++){
-
- iterSet(i, result, S, t);
- }
- return result;
- }
- };