79. 所有子集
79. 所有子集
题目
给定一个整数数组 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] <= 10nums中的所有元素 互不相同
注意
本题与 LeetCode 第 78 题 相同。
解题思路
可以使用回溯算法,通过递归函数实现:
- 定义一个结果集
res用于存储所有的子集。 - 定义一个辅助数组
track用于记录当前回溯路径上的元素。 - 编写回溯算法的核心函数
backtrack,其中参数start控制遍历树枝的起始位置,避免产生重复的子集。 - 在
backtrack函数中,首先将当前路径track加入结果集res,这表示当前的track是一个有效的子集。 - 然后使用循环遍历从
start到数组末尾的元素,对于每个元素,做出选择(将其加入track),然后递归调用backtrack进入下一层。 - 在递归调用返回后,需要撤销选择,即将
track的末尾元素弹出,以便进行下一次选择。 - 通过回溯的过程,可以遍历所有可能的子集。
复杂度分析
时间复杂度:
O(2^n * n),其中n是数组nums的长度。这是因为对于每个元素,都有两种选择:选择或不选择,所以总共有2^n种可能的子集。在每个选择中,都需要花费O(n)的时间来复制当前的路径。空间复杂度:
O(2^n * k)- 空间复杂度主要取决于递归调用的栈空间和存储结果集的空间。
- 递归调用栈的最大深度是数组
nums的长度,所以空间复杂度是O(n)。 - 此外,存储结果集的空间复杂度为
O(总子集个数 * 平均子集大小)。在这里,总子集个数为2^n,平均子集大小为k(题目要求生成大小为k的子集),因此空间复杂度为O(2^n * k)。 - 综合考虑以上两部分,整体的空间复杂度为
O(n + 2^n * k)。 - 在一般情况下,由于
2^n的增长速度较大,因此空间复杂度可以近似表示为O(2^n * k)。
代码
/**
* @param {number[]} nums
* @return {number[][]}
*/
var subsets = function (nums) {
// 用于存储结果
const res = [];
// 用于记录回溯路径
const track = [];
const backtrack = (start) => {
// 前序遍历位置,每个节点的值都是一个子集
res.push([...track]);
// 回溯算法标准框架
for (let i = start; i < nums.length; i++) {
// 做选择
track.push(nums[i]);
// 回溯遍历下一层节点
backtrack(i + 1);
// 撤销选择
track.pop();
}
};
backtrack(0);
return res;
};
