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

(每日一道算法题)子集

78. 子集 - 力扣(LeetCode)

给你一个整数数组 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 中的所有元素 互不相同

方法:DFS回溯法(深度优先搜索)

思路

使用DFS回溯法遍历所有可能的子集组合:

​路径记录​​:使用列表path记录当前已选择的元素

​结果集​​:使用列表ret保存所有找到的子集

​递归设计​​:

  • 每层递归处理一个元素(当前索引n对应的元素)
  • 分别考虑选与不选当前元素的两种情况
  • 递归结束时将路径添加到结果集
关键点解释

​终止条件​​:当处理完所有元素(n == 数组长度),保存当前路径

​选择与回溯​​:

  • 选择当前元素 → 递归处理下一元素 → 回溯移除元素
  • 不选择当前元素 → 直接递归处理下一元素

​无副作用递归​​:使用n+1作为参数传递(而非n++/++n),避免状态污染

代码实现

class Solution {List<List<Integer>> ret; // 结果集List<Integer> path;       // 当前路径(子集)public List<List<Integer>> subsets(int[] nums) {ret = new ArrayList<>();path = new ArrayList<>();dfs(nums, 0); // 从索引0开始DFSreturn ret;}private void dfs(int[] nums, int n) {// 终止条件:已处理所有元素if (nums.length == n) {ret.add(new ArrayList<>(path)); // 保存当前子集return;}// 情况1:选择当前元素path.add(nums[n]);dfs(nums, n + 1);  // 处理下一索引path.remove(path.size() - 1); // 回溯// 情况2:不选择当前元素dfs(nums, n + 1);  // 直接处理下一索引}
}

执行流程示例(nums=[1,2])
递归层当前元素选择情况path状态操作说明
01[1]递归进入下一层
12[1,2]到达终点→保存[1,2]
12不选[1]到达终点→保存[1]
01不选[]递归进入下一层
12[2]到达终点→保存[2]
12不选[]到达终点→保存空集
复杂度分析
  • ​时间复杂度​​:O(N×2^N)
    • 共生成2^N个子集
    • 每个子集平均长度O(N),复制到结果集需O(N)
  • ​空间复杂度​​:O(N)
    • 递归调用栈深度最大为N
    • 路径列表path长度最多为N

高效DFS解法(循环回溯)

算法思路

这种DFS实现采用循环遍历代替选择分支,核心思想是:

  1. ​以不同起始点展开搜索​​:每次递归从pos位置开始遍历数组
  2. ​路径即子集​​:每次进入递归就将当前路径作为子集加入结果集
  3. ​逐步扩展子集​​:从当前位置开始向后扩展,避免重复元素
代码实现 
class Solution {List<List<Integer>> ret; // 结果集List<Integer> path;       // 当前路径(子集)public List<List<Integer>> subsets(int[] nums) {ret = new ArrayList<>();path = new ArrayList<>();dfs(nums, 0); // 从索引0开始DFSreturn ret;}private void dfs(int[] nums, int pos) {ret.add(new ArrayList<>(path)); // 保存当前路径作为子集// 从pos开始向后扩展子集for (int i = pos; i < nums.length; i++) {path.add(nums[i]);      // 包含当前元素dfs(nums, i + 1);       // 递归处理后续元素path.remove(path.size() - 1); // 回溯}}
}

 

执行流程示例(nums=[1,2])
递归层级起始位置当前遍历操作path状态结果集变化
10i=0添加1,dfs(i+1=1)[1]加入空集[]
21循环开始首先保存路径[1]加入[1]
21i=1添加2,dfs(i+1=2)[1,2]加入[1,2]
32-保存路径后循环不执行[1,2]加入[1,2]
32-回溯到上一层[1]
21循环结束回溯到上一层[]
10i=1添加2,dfs(i+1=2)[2]加入[2]
22-保存路径后循环不执行[2]加入[2]

最终结果集:[[],[1],[1,2],[2]]

复杂度分析
  • ​时间复杂度​​:O(N×2^N)
    • 生成2^N个子集
    • 每个子集复制操作需O(N)
  • ​空间复杂度​​:O(N)
    • 递归栈深度最大N
    • 路径存储最多N个元素

 解法一的决策树

解法二的决策树

http://www.xdnf.cn/news/12957.html

相关文章:

  • day51 python CBAM注意力
  • 当文化遇见科技:探秘国际数字影像创新生态高地
  • python爬虫——气象数据爬取
  • 了解Android studio 初学者零基础推荐(4)
  • LangChain + LangSmith + DeepSeek 入门实战:构建代码生成助手
  • 深入理解 React 样式方案
  • VRRP(虚拟路由冗余协议)深度解析
  • 循环语句之while
  • Netty自定义协议解析
  • R语言速释制剂QBD解决方案之一
  • vue3 daterange正则踩坑
  • c++第七天--继承与派生
  • 最好的无线麦克风是那款?2025硬核测评西圣和飞利浦无线领夹麦克风
  • 电子电气架构 --- E/E架构战略
  • 【高性能计算】java连接slurm提交作业,展示作业队列等
  • 【大厂机试题解法笔记】矩阵匹配
  • 电脑插入多块移动硬盘后经常出现卡顿和蓝屏
  • 基于算法竞赛的c++编程(26)指针的高阶用法
  • 基于开源AI智能名片链动2 + 1模式S2B2C商城小程序的沉浸式体验营销研究
  • VSCode 没有添加Windows右键菜单
  • Mac如何配置ZSH并使用Oh-my-zsh?让你的终端更加实用、美观
  • QT开发技术【ffmpeg EVideo录屏软件 一】
  • 多模态学习路线(2)——DL基础系列
  • 【系统架构设计师-2025上半年真题】综合知识-参考答案及部分详解(回忆版)
  • 微服务商城-商品微服务
  • CSS标题下划线动态进入和移开
  • 【春秋云镜】CVE-2023-2130漏洞复现exp
  • 【大模型:知识库管理】--Dify接入RAGFlow 知识库
  • 生命之光-中小企实战运营和营销工作室博客
  • AI智能体终结运维“狼来了“