Given a set of distinct integers, nums, return all possible subsets.

Note: The solution set must not contain duplicate subsets.

For example,

If nums = [1,2,3], a solution is:

[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]

就是求指定集合的所有子集.

三种解法:

  • Recursive (Backtracking) 道理能理解,代码不容易写;
  • Iterative 本文用的解法,好直接,易理解和实现
  • Bit Manipulation 还没学,再补充.

方法1, Recursive (Backtracking)

代码中的注释是我的理解.

// Recursive (Backtracking)
vector<vector<int>> subsets(vector<int>& A) {
sort(A.begin(), A.end()); // sort
vector < vector<int> > res;
vector<int> sub; // 四个参数
// A, 二维res, 临时sub, 待处理数组A元素索引号indx
genSubset(A, res, sub, 0);
return res;
} // DFS:
// box 套 box, 好奇的小儿一直往里面开 box
void genSubset(vector<int>& A, vector<vector<int> >& res, vector<int> sub,
int start) {
res.push_back(sub);
for (int i = start; i < A.size(); i++) {
// 假设 sub = [1]
// sub里压入一个2, sub = [1, 2]
sub.push_back(A[i]); // 看看压入2后, 还有谁?!!
genSubset(A, res, sub, i + 1); // 还有谁的事,由genSubset探查完后,
// 把2弹出去, sub = [1], 然后下轮循环, 看看谁还能和 1 搭个伴,
// 假设A中还有3, 那么下次循环 sub = [1, 3]
// 直到 1 和所有A中剩余元素都结合过
sub.pop_back();
}
}

方法2, Iterative

想法:

就是编程实现下面的东西:

[[]]
[[], []] --> [[], [1]]
[[],[1]] -复制-> [[],[1],[],[1]] -添值-> [[],[1],[2],[1, 2]]
[[],[1],[2],[1, 2]] -复制-> [[],[1],[2],[1, 2],[],[1],[2],[1, 2]] -添值-> [[],[1],[2],[1, 2],[3],[1,3],[2,3],[1, 2, 3]]

上面的例子不太准确(细节写准确太长了,下面针对一个小东西仔细描述过程),但思路是对的.

下面才是程序真正的执行结果:

应该是这样的,我们拿出一小段做解释^^
[[],[1]] -复制-> [[],[1],[]] -添值-> [[],[1],[2]] -复制-> [[],[1],[2],[1]] -添值-> [[],[1],[2],[1,2]]

人家想法,自己代码:

\(O(n^2)\) time, \(O(1)\) extra space.

vector<vector<int>> subsets(vector<int>& A) {
sort(A.begin(), A.end()); // sort
vector < vector<int> > res(1, vector<int>()); // declare res = [[],];
const int n = A.size(); for (int i = 0; i < n; i++) {
const int m = res.size();
for (int j = 0; j < m; j++) {
// 有坑, 注意, 不可妄图写成下面这样:
// res.push_back(res[j].push_back(A[i]));
res.push_back(res[j]); // [[], []]
res.back().push_back(A[i]); // [[], [1]]
}
}
return res;
}

顺便上面代码展示了一些关于c++写代码的副产品,如下:

  1. 声明一个 [[],] 的二维数组: vector < vector<int> > res(1, vector<int>());
  2. 这么写结果不对: for(auto it : res) res.push_back(it.push_back(A[i])); 我晕!
  3. 不能妄图写成这样: res.push_back(res[j].push_back(A[i])); 有点边迭代,边修改数组的意思.
  4. push_back() 和 back() 的区别:
    • coll.push_back()是把一个元素,放入这个容器的末尾,相当于末尾添加一个元素;
    • coll.back()是获取最后一个元素的迭代器,你可以理解为最后一个元素的指针.

接下来是第3种方法,Bit Manipulation 但还没学,再补充.

TODO Bit Manipulation

78. Subsets(中等,集合的子集,经典问题 DFS)的更多相关文章

  1. [LeetCode] 78. Subsets 子集合

    Given a set of distinct integers, S, return all possible subsets. Note: Elements in a subset must be ...

  2. [LeetCode] Subsets 子集合

    Given a set of distinct integers, S, return all possible subsets. Note: Elements in a subset must be ...

  3. LeetCode OJ 78. Subsets

    Given a set of distinct integers, nums, return all possible subsets. Note: Elements in a subset must ...

  4. 刷题78. Subsets

    一.题目说明 题目78. Subsets,给一列整数,求所有可能的子集.题目难度是Medium! 二.我的解答 这个题目,前面做过一个类似的,相当于求闭包: 刷题22. Generate Parent ...

  5. python 实现求一个集合的子集

    概要 今天偶然看到有个关于数学中集合的问题,就突发奇想的想用python实现下求一个集合的子集. 准备 我当然先要复习下,什么是集合,什么是子集? 比较粗犷的讲法,集合就是一堆确定的东西,细致一点的讲 ...

  6. 78. Subsets(M) & 90. Subsets II(M) & 131. Palindrome Partitioning

    78. Subsets Given a set of distinct integers, nums, return all possible subsets. Note: The solution ...

  7. leetcode 78. Subsets 、90. Subsets II

    第一题是输入数组的数值不相同,第二题是输入数组的数值有相同的值,第二题在第一题的基础上需要过滤掉那些相同的数值. level代表的是需要进行选择的数值的位置. 78. Subsets 错误解法: cl ...

  8. [python语法]python中如何判断一个集合是另一个集合的子集?

    问:python中如何判断一个集合是另一个集合的子集? 答:用issubset()方法 语法: A.issubset(B) 返回: True 如果A是B的子集. False 如果A不是B的子集. 样例 ...

  9. 59-python基础-python3-集合-集合常用方法-判断一个集合是否是另一个集合的子集-issubset()-issuperset()

    判断一个集合是否是另一个集合的子集-issubset()-issuperset() 1-issubset() s1.issubset(s) 判断s1是否是s的子集 2-issuperset() 与is ...

随机推荐

  1. Hadoop2.6.0实践:001 伪分布式环境搭建

    ##################### Centos6.4VM_01_os.rar ################################################准备工作/opt ...

  2. HTTP头HOST

    http request header 中的host行的作用 在早期的Http 1.0版中,Http 的request请求头中是不带host行的,在Http 1.0的加强版和Http 1.1中加入了h ...

  3. linux系统命令学习系列-定时任务crontab命令

    上节内容复习: at命令的使用 作业:创建一个任务10分钟后关机 at now+10 minutes at>shutdown at><EOT> 本节我们继续来说例行任务管理命令 ...

  4. Hibernate(四):Hello World

    下载hibernate开发包: 在本章之前需要继承hibernate开发插件到eclipse,详细操作请参考我的博文:<Hibernate(一):安装hibernate插件到eclipse环境& ...

  5. POJ-1182 食物链---并查集(附模板)

    题目链接: https://vjudge.net/problem/POJ-1182 题目大意: 中文题,不多说. 思路: 给每个动物创建3个元素,i-A, i-B, i-C i-x表示i属于种类x,并 ...

  6. Java 线程池原理分析

    1.简介 线程池可以简单看做是一组线程的集合,通过使用线程池,我们可以方便的复用线程,避免了频繁创建和销毁线程所带来的开销.在应用上,线程池可应用在后端相关服务中.比如 Web 服务器,数据库服务器等 ...

  7. Java 接口基础详解

    目录 Java接口示例 实现一个接口 接口实例 实现多个接口 方法签名重叠 接口变量 接口方法 接口默认方法 接口与继承 继承与默认方法 接口与多态性 在Java中,接口是一个抽象类型,有点类似于类, ...

  8. vue-cli的使用

    1.安装node https://nodejs.org/en/download/ 2.webpack安装[我选全局安装] 全局安装 npm install --global webpack 本地安装 ...

  9. rf常用关键字总结

    上传文件choose file 用法:choose file     元素定位          文件路径\\文件名 此处注意:复制的路径是/,需全部替换成\\ 清除Clear Element Tex ...

  10. 机器学习技法:16 Finale

    Roadmap Feature Exploitation Techniques Error Optimization Techniques Overfitting Elimination Techni ...