当前位置: 首页 > news >正文

【LeetCode刷题日记】78.子集

🔥个人主页:代码不加冰(欢迎来访)
🎬作者简介:java后端学习者
❄️个人专栏:LeetCode刷题日记 , 苍穹外卖日记,SSM框架深入,JavaWeb,
命运的结局尽可永在,不屈的挑战却不可须臾或缺!

前言:


大家好,我是代码不加冰,今天是依旧是一整天的课,甚至晚自习还跑不掉了,被迫复习了一天高数和概率论,然后空闲时间玩了玩claude,自己做了点小东西,还是挺有意思的,闲话就不多说了,让我们进入每日 的刷题环节。


摘要:


整体来说还是很简单的,跟前面一个模板。本文介绍了使用回溯算法求解数组所有子集的问题。通过分析子集与组合的区别,作者指出子集问题需要记录搜索树的所有节点而非仅叶子节点。文章详细讲解了回溯三部曲(参数、终止条件、单层逻辑),并给出Java代码实现,通过示例[1,2,3]逐步演示了递归过程。该算法通过从startIndex开始遍历避免重复子集,时间复杂度为O(N×2^N)。最后提供了完整解题代码

题目背景:

给你一个整数数组nums,数组中的元素互不相同。返回该数组所有可能的子集(幂集)。

解集不能包含重复的子集。你可以按任意顺序返回解集。

示例 1:

输入:nums = [1,2,3]输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]

示例 2:

输入:nums = [0]输出:[[],[0]]

提示:

  • 1 <= nums.length <= 10
  • -10 <= nums[i] <= 10
  • nums中的所有元素互不相同

题目分析:

求子集问题和77.组合和131.分割回文串又不一样了。

如果把 子集问题、组合问题、分割问题都抽象为一棵树的话,那么组合问题和分割问题都是收集树的叶子节点,而子集问题是找树的所有节点!

其实子集也是一种组合问题,因为它的集合是无序的,子集{1,2} 和 子集{2,1}是一样的。

那么既然是无序,取过的元素不会重复取,写回溯算法的时候,for就要从startIndex开始,而不是从0开始


什么时候for可以从0开始呢

求排列问题的时候,就要从0开始,因为集合是有序的,{1, 2} 和{2, 1}是两个集合,排列问题我们后续的文章就会讲到的。


以示例中nums = [1,2,3]为例把求子集抽象为树型结构,如下:

从图中红线部分,可以看出遍历这个树的时候,把所有节点都记录下来,就是要求的子集集合


回溯三部曲

递归函数参数

全局变量数组path为子集收集元素,二维数组result存放子集组合。(也可以放到递归函数参数里)

递归函数参数在上面讲到了,需要startIndex。


递归终止条件

从图中可以看出:

剩余集合为空的时候,就是叶子节点。

那么什么时候剩余集合为空呢

就是startIndex已经大于数组的长度了,就终止了,因为没有元素可取了,代码如下:

if (startIndex >= nums.size()) { return; }

其实可以不需要加终止条件,因为startIndex >= nums.size(),本层for循环本来也结束了

  • 单层搜索逻辑

求取子集问题,不需要任何剪枝,因为子集就是要遍历整棵树


代码逐行解析
java public List<List<Integer>> subsets(int[] nums) { List<List<Integer>> result = new ArrayList<>(); backtrack(result, new ArrayList<>(), nums, 0); return result; }
  • result:存放所有子集。

  • 调用backtrack从索引 0 开始构建子集。

java private void backtrack(List<List<Integer>> result, List<Integer> tempList, int[] nums, int start) { // 每次进入递归,先把当前路径(子集)加入结果 result.add(new ArrayList<>(tempList)); for (int i = start; i < nums.length; i++) { tempList.add(nums[i]); // 选择当前元素 backtrack(result, tempList, nums, i + 1); // 继续往后选 tempList.remove(tempList.size() - 1); // 撤销选择(回溯) } }

4. 执行过程图解(以 nums = [1,2,3] 为例)

text 初始:tempList = [] → 加入 [] 到结果 i=0: 选1 → tempList=[1] → 加入 [1] i=1: 选2 → [1,2] → 加入 [1,2] i=2: 选3 → [1,2,3] → 加入 [1,2,3] i=3 退出 撤销3 → [1,2] i=2: 选3 → [1,3] → 加入 [1,3] 撤销3 → [1] 撤销2 → [1] 撤销1 → [] i=1: 选2 → [2] → 加入 [2] i=2: 选3 → [2,3] → 加入 [2,3] 撤销3 → [2] 撤销2 → [] i=2: 选3 → [3] → 加入 [3] 撤销3 → [] 最终结果顺序: [] [1] [1,2] [1,2,3] [1,3] [2] [2,3] [3]

5. 为什么不会重复

  • 每次递归只从start开始,不会回头选之前已经考虑过的元素。

  • 保证了每个子集生成时,元素顺序与数组原始顺序一致,避免了[1,2][2,1]这种重复。

6. 复杂度分析

  • 时间复杂度:O(N × 2^N)
    一共有 2^N 个子集,每个子集复制到结果时平均长度 O(N)。

  • 空间复杂度:O(N)(递归栈深度) + O(2^N × N)(存储所有结果)。


题目答案:

class Solution { public List<List<Integer>> subsets(int[] nums) { List<List<Integer>> result = new ArrayList<>(); backtrack(result, new ArrayList<>(), nums, 0); return result; } private void backtrack(List<List<Integer>> result, List<Integer> tempList, int[] nums, int start) { // 将当前子集加入结果集 result.add(new ArrayList<>(tempList)); // 从 start 开始,尝试将每个元素加入子集 for (int i = start; i < nums.length; i++) { tempList.add(nums[i]); // 选择当前元素 backtrack(result, tempList, nums, i + 1); // 递归处理下一个元素 tempList.remove(tempList.size() - 1); // 撤销选择 } } }

结语:

如果对你有帮助,请点赞,关注,收藏,你的支持就是我最大的鼓励!

http://www.cnnetsun.cn/news/2840449.html

相关文章:

  • 3分钟生成专业短视频:Pixelle-Video AI全自动视频创作工具完全指南
  • 多维聚合数据操作:预计算、实时补丁与语义层三层架构
  • OneNet MQTT接入避坑指南:手把手解决Python连接、数据上报和Topic订阅的常见问题
  • Mythos安全大模型:自动漏洞利用与开发者原生安全实践
  • 从发送报文到过滤接收:用USB-CAN TOOL软件做车载ECU通信调试的实战笔记
  • 云存储与数据库的本质区别:从分层契约看数据服务选型
  • AI NFT 生成与链上验证:去中心化创作经济,从算法艺术到可验证原创
  • 别再只用UUID v4了!5分钟搞懂UUID的5个版本,选对场景性能翻倍
  • 蓝桥杯嵌入式省赛复盘:第九届赛题里那些新手容易踩的EEPROM和长短按按键的坑
  • 长春到天津物流专线靠谱吗?5万单数据验证的本土专线给出了真实答案
  • YL1621 全引脚 HBM ESD 耐压实测数据(附逐引脚清单)
  • Arduino小球平衡台全套搭建资料:PID代码+3D打印件+接线调试指南
  • 现场五招验苗技巧,不用专业设备筛选优质鱼苗
  • 湘美谈教育AI经验集锦:有些东西,它们很难蒸馏
  • 2026年金属粉末粘合剂实力厂家,选购注意事项汇总
  • 不增项的义乌义东花园装修
  • 2026年城市照明工程4大核心痛点及解决方案
  • 车辆CTRV运动建模下的C++无迹卡尔曼滤波工程实现(含雷达融合测试与可视化)
  • 甩手图省事POD生图功能:利用AI中小卖家3步打造爆款定制产品
  • Java面试翻车现场:谢飞机大战严肃面试官,3轮提问笑到头掉!
  • 单层VQ-VAE如何通过码本优化逆袭分层架构?
  • 手动调节迭代次数的ILC控制MATLAB实例与误差变化可视化资料
  • 告别鼠标流!IDEA 2023.3最全快捷键清单与高效配置指南,让你的编码速度翻倍
  • Unlock Music音乐解锁工具:3分钟快速解密所有加密音乐格式
  • 生产环境部署 Milvus 集群:Kubernetes 编排、高可用与监控告警
  • 从CenterPoint看3D目标检测演进:为什么“点”比“框”更适合自动驾驶?
  • 别再为文档水印发愁了!手把手教你用Java反编译搞定Aspose.Words 19.1授权验证
  • Next.js App Router 与 RSC 深度实践:服务端架构与性能优化,从 Pages 到 App 的范式迁移
  • 21.RAG进阶(Advanced RAG)-RAG存在的问题(Advanced RAG)
  • 航空客户流失预测全流程实战包:清洗数据+决策树建模+可视化报告