78. 子集
一、题目描述
给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明:解集不能包含重复的子集。
示例:
输入: nums = [1,2,3]
输出:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
二、解题思路 & 代码
2.1 迭代
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
res = [[]]
for i in nums:
res = res + [[i] + num for num in res]
return res
复杂度分析
- 时间复杂度: O ( N × 2 N ) \mathcal{O}(N \times 2^N) O(N×2N),生成所有子集,并复制到输出结果中。
- 空间复杂度: O ( N × 2 N ) \mathcal{O}(N \times 2^N) O(N×2N),这是子集的数量。
对于给定的任意元素,它在子集中有两种情况,存在或者不存在(对应二进制中的 0 和 1)。因此,N 个数字共有 2 N 2^N 2N 个子集。
2.2 递归(回溯)
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
res = []
n = len(nums)
def helper(i, tmp):
res.append(tmp)
for j in range(i, n):
helper(j + 1,tmp + [nums[j]] )
helper(0, [])
return res
复杂度分析
- 时间复杂度: O ( N × 2 N ) \mathcal{O}(N \times 2^N) O(N×2N),生成所有子集,并复制到输出集合中。
- 空间复杂度: O ( N × 2 N ) \mathcal{O}(N \times 2^N) O(N×2N),存储所有子集,共 N 个元素,每个元素都有可能存在或者不存在。
2.3 字典排序(二进制排序) 子集
参考:
LeetCode官方题解
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
n = len(nums)
output = []
for i in range(2**n, 2**(n + 1)):
# generate bitmask, from 0..00 to 1..11
bitmask = bin(i)[3:]
# append subset corresponding to that bitmask
output.append([nums[j] for j in range(n) if bitmask[j] == '1'])
return output
复杂度分析
- 时间复杂度: O ( N × 2 N ) \mathcal{O}(N \times 2^N) O(N×2N)
- 空间复杂度: O ( N × 2 N ) \mathcal{O}(N \times 2^N) O(N×2N)
参考:
==================================================
90. 子集 II
一、题目描述
给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明:解集不能包含重复的子集。
示例:
输入: [1,2,2]
输出:
[
[2],
[1],
[1,2,2],
[2,2],
[1,2],
[]
]
二、解题思路 & 代码
2.1 递归
直接根据 78 题 的思路去做的,这个比较好改,我们只需要判断当前数字和上一个数字是否相同,相同的话跳过即可。当然,要把数字首先进行排序。
class Solution:
def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
res = []
n = len(nums)
nums.sort()
def helper(idx, tmp):
res.append(tmp)
for i in range(idx, n):
if i > idx and nums[i] == nums[i-1]:
continue
helper(i+1, tmp + [nums[i]])
helper(0, [])
return res
2.2 迭代
class Solution:
def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
if not nums: return []
nums.sort()
res = [[]]
cur = []
for i in range(len(nums)):
if i > 0 and nums[i - 1] == nums[i]:
cur = [tmp + [nums[i]] for tmp in cur]
else:
cur = [tmp + [nums[i]] for tmp in res]
res += cur
return res