
LeetCode:Subsets I II
发布日期:2025-04-05 03:55:16
浏览次数:10
分类:精选文章
本文共 2894 字,大约阅读时间需要 9 分钟。
求集合的所有子集问题
求集合的所有子集,需要考虑集合是否有重复元素以及元素的顺序要求。以下是详细的解决方案和分析。
一、给定问题描述
问题要求:
- 返回集合的所有子集。
- 子集中的元素必须按非降序排列。
- 子集不能包含重复项。
例子分析:
- 对于集合 [1,2,3],所有子集包括:
[ ]
,[1]
,[2]
,[3]
,[1,2]
,[1,3]
,[2,3]
,[1,2,3]
。 - 对于集合 [1,2,2],所有子集包括:
[ ]
,[1]
,[2]
,[2]
(重复),[1,2,2]
,[2,2]
,[1,2]
。
三、解决方案
算法一:DFS方法
代码实现:
#include#include using namespace std;class Solution {private: vector > res;public: vector > subsets(vector &S) { // 先排序 sort(S.begin(), S.end()); res.clear(); vector tmpres; dfs(S, 0, tmpres); return res; } void dfs(vector &S, int iend, vector &tmpres) { if (iend == S.size()) { res.push_back(tmpres); return; } // 计算当前位置及之前的相同元素数量 int firstSame = iend; while (firstSame >= 0 && S[firstSame] == S[iend]) firstSame--; firstSame++; int sameNum = iend - firstSame; // 检查是否需要新增 // 如果前面没有该元素或者本应有该元素但选的数量不足 if (sameNum == 0 || (tmpres.size() >= sameNum && tmpres[tmpres.size() - sameNum] == S[iend])) { // 选择当前元素 tmpres.push_back(S[iend]); dfs(S, iend + 1, tmpres); tmpres.pop_back(); } // 不选择当前元素 dfs(S, iend + 1, tmpres); }};
算法工作原理:
- 排序:先对集合进行排序,确保子集按非降序生成。
- DFS递归:递归生成所有可能的子集,每次选择或不选择当前元素。
- 去重机制:通过计算前面相同元素的数量,确保不重复生成包含相同元素的子集。
算法二:迭代方法
- 算法三:二进制方法(适用于无重复元素)
- 总结
选择合适的算法:
- 如果集合中没有重复元素,可以使用二进制方法或迭代方法。
- 如果集合中存在重复元素,建议使用基于DFS的算法,确保生成唯一的子集。
注意事项:
- 理解子集生成的顺序和方式,避免重复。
- 高效处理重复元素的方法,减少不必要的递归深度或循环次数。
#include#include using namespace std;class Solution {private: vector > res;public: vector > subsets(vector &S) { sort(S.begin(), S.end()); res.clear(); vector empty; res.push_back(empty); int last = S.empty() ? 0 : S[0]; int opResNum = 1; for (int i = 0; i < S.size(); ++i) { if (S[i] != last) { last = S[i]; opResNum = res.size(); } int resSize = res.size(); int opRes = resSize - opResNum; for (int j = opRes; j < resSize; ++j) { res.push_back(res[j]); res.back().push_back(S[i]); } } return res; }};
#include#include using namespace std;class Solution {private: vector > res;public: vector > subsets(vector &S) { sort(S.begin(), S.end()); if (S.empty()) { return { {} }; } res.clear(); res.push_back({}); unsigned long long bit = 1; int len = S.size(); vector tmp; while (bit <= (1LL << len) - 1) { tmp.clear(); unsigned long long cur = bit; for (int i = 0; i < len; ++i) { if (cur & 1) { tmp.push_back(S[i]); } cur >>= 1; } res.push_back(tmp); bit++; } return res; }};
通过以上方法,可以高效地生成集合的所有子集,确保在说明顺序和唯一性要求下,正确性和性能。
发表评论
最新留言
关注你微信了!
[***.104.42.241]2025年04月30日 19时49分21秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
Java基础学习总结(47)——JAVA输入输出流再回忆
2025-04-02
Java基础学习总结(4)——对象转型
2025-04-02
Java基础学习总结(4)——对象转型
2025-04-02
Java基础学习总结(51)——JAVA分层理解
2025-04-02
Java基础学习总结(53)——HTTPS 理论详解与实践
2025-04-02
Java基础学习总结(54)——JSON和Map转换的工具类
2025-04-02
Java基础学习总结(56)——学Java必知十大学习目标
2025-04-02
Java基础学习总结(57)——Jrebel插件热部署
2025-04-02
Java基础学习总结(59)——30 个java编程技巧
2025-04-02
Java基础学习总结(5)——多态
2025-04-02
Java基础学习总结(63)——Java集合总结
2025-04-02
Java基础学习总结(64)——Java内存管理
2025-04-02
Java基础学习总结(66)——配置管理库typesafe.config教程
2025-04-02
Java基础学习总结(67)——Java接口API中使用数组的缺陷
2025-04-02
Java基础学习总结(70)——开发Java项目常用的工具汇总
2025-04-02
Java基础学习总结(73)——Java最新面试题汇总
2025-04-02
Java基础学习总结(75)——Java反射机制及应用场景
2025-04-02
Java基础学习总结(76)——Java异常深入学习研究
2025-04-02
Java基础系列
2025-04-03
Kubernetes 自定义服务的启动顺序
2025-04-03