【LeetCode】78. 子集 & 90. 子集 II

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

复杂度分析

  1. 时间复杂度: O ( N × 2 N ) \mathcal{O}(N \times 2^N) ,生成所有子集,并复制到输出结果中。
  2. 空间复杂度: O ( N × 2 N ) \mathcal{O}(N \times 2^N) ,这是子集的数量。

对于给定的任意元素,它在子集中有两种情况,存在或者不存在(对应二进制中的 0 和 1)。因此,N 个数字共有 2 N 2^N 个子集。

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  

复杂度分析

  1. 时间复杂度: O ( N × 2 N ) \mathcal{O}(N \times 2^N) ,生成所有子集,并复制到输出集合中。
  2. 空间复杂度: O ( N × 2 N ) \mathcal{O}(N \times 2^N) ,存储所有子集,共 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

复杂度分析

  1. 时间复杂度: O ( N × 2 N ) \mathcal{O}(N \times 2^N)
  2. 空间复杂度: O ( N × 2 N ) \mathcal{O}(N \times 2^N)

参考:

  1. LeetCode官方题解
  2. LeetCode题解

==================================================

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

猜你喜欢

转载自blog.csdn.net/weixin_41888257/article/details/108366693