子集
题目描述:
解题思路
python3
- 第一种:层次迭代。我们很容易能从子集中找出规律,首先定义最终子集
res_subset
为[[]]
,也作为首层,然后将nums
从头开始遍历,每遍历一次就到下一层,举例比如nums = [1,2,3]
,然后根据首层的集合只有一个空集,也就是数目为1
,将这个集合都加上nums[0]
,也就是nums
的第一个数,就变成了[1]
,再放回res_subset
中,此时最终子集中就变成了[[], [1]]
,同理,下一层的要加入的数为nums[1]
,将每个最终子集中的每个集合都加上这个数,就变成了[2]
和[1,2]
再放回最终子集,所以得到一个新的最终子集[[], [1], [2], [1,2]]
,同理,下面的步骤就和上面一样,最后直到nums
每个数都遍历完了,全部子集就得到了。 - 时间复杂度:O(N^2)
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
res_subset = [[]]
for i in range(len(nums)):
for j in range(len(res_subset)):
res_subset.append(res_subset[j] + [nums[i]])
return res_subset
- 第二种:回溯递归。我们额外定义函数来递归计算所有子集。
- 时间复杂度:O(N 2^n)
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
res_subset = self.solve_subset([], 0, [], nums)
return res_subset
def solve_subset(self, res, front, part, num):
res.append(part)
for i in range(front, len(num)):
self.solve_subset(res, i+1, part + [num[i]], num)
return res
- 第三种:二进制位运算法。
- 这个方法很厉害,我们将二进制
1 << len(nums)
进行遍历,然后看是否满足i >> j & 1 ==1
。 - 时间复杂度:O(N^2)
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
res_subsets = []
for i in range(1 << len(nums)):
part = []
for j in range(len(nums)):
if i >> j & 1 == 1:
part.append(nums[j])
res_subsets.append(part)
return res_subsets