684 字
3 分钟
子集

题目描述
给你一个整数数组 nums
,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
解题思路
- 回溯算法框架:采用 DFS 回溯法遍历所有可能组合,从空集开始逐步添加元素
- 路径记录:维护当前路径
path
,每次递归时记录当前生成的子集 - 索引控制:使用
start
参数确保元素按顺序选择,避免重复组合 - 递归展开:每层递归决策”是否添加当前元素”并进入下一层
- 无剪枝设计:题目要求所有子集,故无需剪枝
关键洞察
- 树形结构特性:子集生成可视为二叉树遍历 - 每个元素有”选/不选”两种状态
- 路径复用机制:回溯时通过
pop()
操作复用数组空间,避免额外内存分配 - 自动去重原理:索引递增保证元素选择顺序固定,自然避免重复子集
- 空集处理:初始空路径
[]
确保包含空集 - 即时收集:每次递归入口记录当前路径,确保所有中间状态都被收集
复杂度分析
指标 | 说明 |
---|---|
时间复杂度 | O(n × 2ⁿ):生成 2ⁿ 个子集,每个子集平均长度 n/2,复制需 O(n) 时间 |
空间复杂度 | O(n × 2ⁿ):存储结果所需空间(递归栈 O(n) 可忽略) |
代码实现
递归回溯法
/** * @param {number[]} nums * @return {number[][]} */var subsets = function (nums) { const result = []; const n = nums.length;
const dfs = (start, item) => { result.push(item); for (let i = start; i < n; i++) { dfs(i + 1, [...item, nums[i]]) } }
dfs(0, []);
return result;};
迭代法(空间优化)
/** * @param {number[]} nums * @return {number[][]} */const subsets = (nums) => { let res = [[]]; for (const num of nums) { const newSets = res.map(set => [...set, num]); res = [...res, ...newSets]; } return res;};
位运算法(常数优化)
/** * @param {number[]} nums * @return {number[][]} */const subsets = (nums) => { const n = nums.length; const total = 1 << n; const res = Array(total); for (let mask = 0; mask < total; mask++) { const subset = []; for (let i = 0; i < n; i++) { if (mask & (1 << i)) subset.push(nums[i]); } res[mask] = subset; } return res;};
实际应用场景
- 特征选择:机器学习中枚举特征组合`
- 权限组合:系统权限的幂集生成`
- 组合优化:穷举搜索问题解空间`
- 测试用例生成:软件测试中参数组合覆盖`