78.子集

78.子集

1.题目

在这里插入图片描述

2.我的解决方案

太菜了,这道题用的思路不太会

3.官方的解决方案

回溯法:从选择和不选择的角度出发

class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        # 采用回溯法,使用深度优先遍历
        # 二叉树所有的叶子结点都是问题的解
        def dfs(nums, length, index, path, res):
            if index == length:    # 到了递归的叶子结点
                res.append(path[:])  # 将路径状态添加到结果当中(必须是path[:], 不能只是path))
                return
            dfs(nums, length, index+1, path, res)   # 不考虑该元素,进行下一层递归
            path.append(nums[index])    # 考虑该元素,就将其加入路径变量
            dfs(nums, length, index+1, path, res)
            path.pop()  # 回溯算法状态重置,在递归前做了什么操作,就在递归后做相反的操作

        length = len(nums)
        self.res = []
        path = []
        dfs(nums, length, 0, path, self.res) # 输入数组,输入数组的长度,当前考虑的元素的下标,传入路径变量(栈),结果

        return self.res
  • 时间复杂度: O ( n ∗ 2 n ) O(n*2^n) O(n2n) :形成二叉树的所有 2 n + 1 2^{n+1} 2n+1结点 O ( 2 n ) O(2^n) O(2n),保存一次结点所占用的时间为 O ( n ) O(n) O(n)
  • 空间复杂度 O ( n ) O(n) O(n) :形成二叉树的所有 2 n + 1 2^{n+1} 2n+1个结点,每个结点所占用的空间为 O ( n ) O(n) O(n)
    关于列表中插入列表遇到的问题解决方案:点击查看

按照求全排列的思路

在这里插入图片描述

class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        # 采用回溯法,使用深度优先遍历
        # 按照全排列的思路,绘制的是多叉树
        def dfs(nums, length, begin, path, res):
            res.append(path[:]) # 前序遍历
            for i in range(begin, length):  
                # i表示从num[i]为根结点,作为begin进行深度优先遍历,到了叶子结点,i++,换一个num[i]作为根节点,继续向下遍历
                path.append(nums[i])    # 考虑该元素,就将其加入路径变量
                dfs(nums, length, i+1, path, res)
                path.pop()  # 回溯算法状态重置,在递归前做了什么操作,就在递归后做相反的操作

        length = len(nums)
        self.res = []
        path = []
        dfs(nums, length, 0, path, self.res) # 输入数组,输入数组的长度,当前考虑的元素的下标,传入路径变量(栈),结果
        
        return self.res
  • 时间复杂度: O ( n ∗ 2 n ) O(n*2^n) O(n2n) :形成二叉树的所有 2 n + 1 2^{n+1} 2n+1结点 O ( 2 n ) O(2^n) O(2n),保存一次结点所占用的时间为 O ( n ) O(n) O(n)
  • 空间复杂度 O ( n ) O(n) O(n) :形成二叉树的所有 2 n + 1 2^{n+1} 2n+1个结点,每个结点所占用的空间为 O ( n ) O(n) O(n)

位运算

在这里插入图片描述

class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        # 采用位运算
        # 位运算和子集中元素的选与不选有结构上的巧合
        length = len(nums)
        size = 1 << length  # 子集的个数(左移相当于乘以2)
        res = []
        for i in range(0, size):	# 每个数字都对应了结果集中的一个子集元素
            subset = []	
            for j in range(0, length):	# 从nums开始中开始筛选放入
                # 对应的i右移j位,来从右到左判断是否选择该元素进入子集
                if((i >> j) & 1 == 1):  # 说明这个数是子集当中的元素,将其添加到子集当中
                    subset.append(nums[j])
            res.append(subset)
        return res
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值