LeetCode 78. 子集(Subsets)

78. 子集

题目描述

给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。

解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。

示例 1:

输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]

示例 2:

输入:nums = [0]
输出:[[],[0]]

解题思路:回溯法(Backtracking)

核心思想

  • 子集问题的本质是在每个元素面前做“选”或“不选”

  • 使用回溯法逐步构造出所有可能的组合

  • 使用参数 start 控制从哪里开始选数字,确保不重复、不回头

✅Python 实现 

class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        res = []

        def backtrack(start, path):
            res.append(path[:])
            for i in range(start, len(nums)):
                # start 是用来控制递归中从哪里开始选数字的
                # 避免重复、保证子集不重复,且不回头选择已经处理过的元素。
                path.append(nums[i])
                backtrack(i + 1, path)
                path.pop()
        
        backtrack(0, [])
        return res

⏱️复杂度分析 

项目 复杂度 说明
时间复杂度 O(n × 2ⁿ) 每个元素有选/不选两种状态,共 2ⁿ 个子集,每个子集最多 n 个元素
空间复杂度 O(n) 递归栈最大深度为 n

常见易错点 

错误点 正确做法说明
没有复制 path 要用 path[:] 添加子集副本
忘记 start 控制递归范围 start 确保不重复选择已处理过的元素
误把子集当作排列处理 子集不需要考虑顺序,只控制是否选入即可

扩展解法(非递归二进制法) 

class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        res = []
        n = len(nums)
        for mask in range(1 << n):
            subset = []
            for i in range(n):
                if mask & (1 << i):
                    subset.append(nums[i])
            res.append(subset)
        return res

这种解法将每个子集映射为一个 n 位二进制数,1 表示选,0 表示不选。 

总结

  • 本题是回溯入门题,属于组合型问题。

  • 建议掌握两种方法:

    • ✅ 回溯(递归)

    • ✅ 位运算(非递归)

 

你可能感兴趣的:(leetcode,算法,职场和发展)