Skip to main content

78.子集

标签: array, backtracking, bit-manipulation

难度: Medium

通过率: 79.78%

原题链接: https://leetcode.com/problems/subsets/description/

题目描述

给定一个由唯一元素组成的整数数组 numsnums,返回所有可能的子集(幂集)。解集不能包含重复的子集。返回解集的顺序可以是任意的。

解题思路

要得到一个集合的所有子集,可以使用回溯法或者位运算来解决。回溯法是一种常用的全排列、组合或者子集问题的求解方法:

  1. 初始化一个空数组来存储结果。
  2. 使用递归函数来遍历原数组,每次递归选择是否把当前元素加入当前子集中。
  3. 递归终止的条件是遍历完所有元素。
  4. 每次递归都保存当前子集到结果数组。
  5. 最后返回结果数组。

位运算方法

每个数有两种状态:在子集中或不在子集中,对于一个有nn个元素的数组来说,总共有2n2^n种子集,每一个子集可以用一个长度为nn的二进制数来表示,选择1表明在子集中,0表明不在子集中,因此:

  1. 枚举从002n12^n-1的所有数。
  2. 对于每个数,将其二进制表示的位作为是否选择对应数组元素的标志。

代码实现

def subsets(nums):
result = [] # 存放所有子集
subset = [] # 当前递归路径对应的子集

def backtrack(start):
# 每次递归都记录当前子集
result.append(subset.copy())
for i in range(start, len(nums)):
# 选择当前数
subset.append(nums[i])
# 递归产生下一个子集
backtrack(i + 1)
# 回溯前恢复状态
subset.pop()

backtrack(0)
return result

# 测试
print(subsets([1, 2, 3]))

复杂度分析

时间复杂度:O(2nn)O(2^n \cdot n),其中nn是数组的长度,每个子集的生成涉及复制和递归。 空间复杂度:O(n)O(n),递归栈的深度和中间变量存储所需的空间。