90. 子集 II

90. 子集 II

1.题目

在这里插入图片描述

2.官方的解决方案

解法一:使用itertools.combinations(list, n)

class Solution:
    def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
        # 解法一: 使用组合函数和extend函数
        # (了解该方法即可,一般考核的时候不要尝试)
        res = []
        nums.sort() #关键行
        for i in range(len(nums)+1):
            res.extend(list(set(itertools.combinations(nums, i))))
        # 疑惑的是为什么内部的集合会被平台自动转成列表
        return res

解法二:使用collections.Counter()

class Solution:
    def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
        # 解法一: 使用组合函数和extend函数
        # (了解该方法即可,一般考核的时候不要尝试)
        res = [[]]
        for key, value in collections.Counter(nums).items():
            res = [pre + [key]*cnt for pre in res for cnt in range(value+1)]
            """
            不断迭代,将前一轮的,根据cnt,在每个答案后面添加key
            """
        return res

解法三:一般的解决方法,回溯法

class Solution:
    def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
        def backtrack(path, index, nums, check, res):
            if index == len(nums):
                res.append(path[:])
                return
            """
                对于当前选择的数x,若前面有与其相同的数y,且没有选择y,此时包含x的子集,必然会出现在包含y的所有子集中。
                我们可以通过判断这种情况,来避免生成重复的子集。
                代码实现时,可以先将数组排序;迭代时,若发现没有选择上一个数,且当前数字与上一个数相同,则可以跳过当前生成的子集。

                解释:当回溯return回来时,比如形成[1,2,2], return 到[1,2]. check[2]=0
                继续执行不考虑的情况,形成[1,2], return , return, check[1]=0
                继续执行不考虑的情况,如果不设置check[1]=0,就会再出现一个[1,2]
                所以对于当前选择的数x,若前面有与其相同的数y,且没有选择y,会造成重复
                解决方法:数组排序, 迭代时,若发现没有选择上一个数,且当前数字与上一个数相同,则可以跳过当前生成的子集。
            """
            if index==0 or nums[index]!=nums[index-1] or check[index-1]==1:
                check[index] = 1
                backtrack(path+[nums[index]], index+1, nums, check, res)
                check[index] = 0
            backtrack(path, index+1, nums, check, res)  # 考虑不要index号元素的情况下

        nums.sort()
        res = []
        path = []
        check = [0] * len(nums)
        backtrack(path, 0, nums, check, res)
        return res
  • 时间复杂度: O ( 2 n ) O(2^n) O(2n)
  • 空间复杂度: O ( n ) O(n) O(n)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值