LeetCode 90 Medium 求子集2 Python

本文探讨了在处理含有重复元素的集合时,如何高效生成所有唯一子集的方法。通过对比三种算法——递归/回溯、二进制解法及迭代法,详细解析了去重与排序技巧,确保子集生成的正确性和效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

方法一:

    算法:递归/回溯

    思路

        和第78题,求子集思路类似,但是不同的是这里要【去重】,以及【排序】

            n个元素的集合子集数目有2^n次方个,但是由于集合中有重复元素,所以实际的集合数目达不到这么多

        最直观的去重思想就是用set✅,但是要注意在python中,list对象是不能放到set中的,所以放到

        set中的应该是tuple元组类型,其实set只是辅助去重,所以在添加的时候,只要判断tuple()后的

        元组是否在set中就可以了,不在的话,就可以添加到result的中,否则的话就不添加,当然了,同时

        也要更新set,也可以不用result直接用set最后将set转为list也ok,但是这样和直接用list类型的

        result相比算是用空间换时间吧

            这里要注意使用递归生成所有子集的时候要先把原来的数组进行排序后再进行递归,如果不进行排序的

        话,(2,1,2)与(1,2,2)将被视为是两个不同的子集,但是事实上二者是同一个子集,将数组排序后

        进行子集的生成可以延续78题中一个个子集元素是按层自上而下添加进去的思想。

    复杂度分析

        时间:O2^N,实际上遍历了所有O2^N个子集(也是O2^N种可能的情况),只不过重复集合不添加罢了

        空间:O2^N,递归栈空间以及存储子集的result,res_set的空间

def subsetsWithDup0( nums):

    def generate(i, nums, subset, result, res_set):

        if i >= len(nums):

            return

        generate(i + 1, nums, subset[:], result, res_set)

        subset.append(nums[i])

        if tuple(subset) not in res_set:

            result.append(subset)

            res_set.add(tuple(subset))

        generate(i + 1, nums, subset[:], result, res_set)

    nums.sort()

    result = [[]]

    generate(0, nums, [], result, set())

    return result

方法二:

    与78题中的二进制解法类似,只是这里也添加了【排序】和【set去重】的步骤

def subsetsWithDup1( nums):

    nums.sort()

    all_set = 1 << len(nums)

    result = []

    res_set = set()

    for i in range(all_set):

        subset = []

        for j in range(len(nums)):

            # 或者1<<(len(nums)-1-j) & i

            if 1 << j & i:

                subset.append(nums[j])

        if tuple(subset) not in res_set:

            result.append(subset)

            res_set.add(tuple(subset))

    return result

方法三:

    与78题中的二进制解法类似,只是这里也添加了【排序】和【set去重】的步骤

def subsetsWithDup2( nums):

    nums.sort()

    res_set = set()

    ans = [[]]

    for num in nums:

        for exist in ans[:]:

            tmp = [num]+exist

            if tuple(tmp) not in res_set:

                ans.append(tmp)

                res_set.add(tuple(tmp))

    return ans

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值