Featured image of post subsets

subsets

78. 子集

分析

回溯法

  1. 思路
    • 每个元素都有两种状态:选入当前子集或不选入当前子集
    • 对每个元素进行选择,并递归处理剩余元素
    • 当递归到数组末尾时,将当前子集 path 加入结果集 res
  2. 步骤
    • res 存储所有子集结果
    • path 存储当前子集路径
    • 用递归函数 dfs(nums, u) 表示从索引 u 开始构造子集
      • 如果索引到达数组末尾,将当前路径加入结果集
      • 否则:
        • 跳过当前元素,继续递归
        • 包含当前元素,继续递归,并在递归结束后回溯状态

位运算枚举

  1. 位运算思路

    • 每个子集可以看作长度为 n 的二进制数,每一位 1 表示对应的数组元素被选中
    • 枚举从 02^n - 1 的所有整数,用二进制表示子集选择情况
    • 对于每个整数:
      • 遍历其二进制的每一位,若某一位为 1,将对应位置的数组元素加入当前子集
        • 将生成的子集加入结果集
  2. 步骤

    • 初始化结果集 res
    • 遍历从 02^n - 1 的整数,用位运算检查每一位是否为 1
    • 若某位为 1,将对应的数组元素加入当前子集 path
    • 枚举结束后返回结果集 res

时间复杂度

每个元素有两种状态(选或不选),总状态数为 2^n。遍历每个状态生成子集,总时间复杂度 O(n^2)

空间复杂度

递归调用栈深度为 O(n),路径数组 path 最多占用 O(n),总空间复杂度为 O(n)

C++代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
class Solution
{
public:
    std::vector<std::vector<int>> res;   // 存储所有子集
    std::vector<int> path;              // 当前子集路径

    vector<vector<int>> subsets(vector<int>& nums)
    {
        dfs(nums, 0);                   // 从索引 0 开始回溯
        return res;
    }

    void dfs(std::vector<int>& nums, int u)
    {
        // 递归终止条件:索引越界时,将当前路径加入结果集
        if (u == nums.size())
        {
            res.push_back(path);
            return;
        }

        // 不选择当前元素,继续递归
        dfs(nums, u + 1);

        // 选择当前元素,加入路径并继续递归
        path.push_back(nums[u]);
        dfs(nums, u + 1);

        // 回溯状态,移除当前元素
        path.pop_back();
    }
};


class Solution
{
public:
    vector<vector<int>> subsets(vector<int>& nums)
    {
        std::vector<std::vector<int>> res;  // 存储所有子集
        int n = nums.size();

        // 枚举所有可能的子集,用二进制表示
        for (int i = 0; i < (1 << n); ++i)
        {
            std::vector<int> path;          // 当前子集
            for (int j = 0; j < n; ++j)
            {
                if ((i >> j) & 1)           // 若第 j 位为 1,加入对应元素
                    path.push_back(nums[j]);
            }
            res.push_back(path);            // 将当前子集加入结果集
        }
        return res;
    }
};
Built with Hugo
Theme Stack designed by Jimmy