78. 子集

中等 · 回溯 · 位运算

题目

78. 子集
官方题解

方法1:回溯

刚开始写错了,写了个带长度的全排列

 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
class Solution {
public:
    vector<vector<int>> res;

    void dfs(vector<int> nums, int u, int length, vector<int> tmp, bool st[]) {
        if (u == length) {
            res.push_back(tmp);
        }

        for (int i = 0; i < nums.size(); i ++) {
            if (!st[i]) {
                st[i] = true;
                tmp.push_back(nums[i]);
                dfs(nums, u + 1, length, tmp, st);
                st[i] = false;
                tmp.pop_back();
            }
        }
    }

    vector<vector<int>> subsets(vector<int>& nums) {
        int n = nums.size();

        bool st[n];
        vector<int> tmp;
        for (int i = 0; i <= n; i ++) {
            memset(st, false, sizeof st);
            tmp.clear();
            dfs(nums, 0, i, tmp, st);            
        }
        return res;  
    }
};

正确代码

 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
class Solution {
public:
    vector<vector<int>> res;

    void dfs(vector<int> nums, int u, int length, vector<int> tmp) {
        if (tmp.size() == length) {
            res.push_back(tmp);
            return;
        }

        if (u == nums.size()) {
            return ;
        }

        // put
        tmp.push_back(nums[u]);
        dfs(nums, u + 1, length, tmp);
        tmp.pop_back();

        // not put
        dfs(nums, u + 1, length, tmp);
    }

    vector<vector<int>> subsets(vector<int>& nums) {
        int n = nums.size();

        bool st[n];
        vector<int> tmp;
        for (int i = 0; i <= n; i ++) {
            tmp.clear();
            dfs(nums, 0, i, tmp);
        }
        return res;  
    }
};

时间复杂度:O(N * 2^N) 空间复杂度:O(N)

因为我是在之前的排列代码上改的,所以其实并不需要用到length参数,可以直接在dfs里把结果加入res

 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
class Solution {
public:
    vector<vector<int>> res;
    vector<int> tmp;

    void dfs(vector<int> nums, int u) {
        if (u == nums.size()) {
            res.push_back(tmp);
            return;
        }

        dfs(nums, u + 1);

        tmp.push_back(nums[u]);
        dfs(nums, u + 1);
        tmp.pop_back();
    }


    vector<vector<int>> subsets(vector<int>& nums) {
        int n = nums.size();

        dfs(nums, 0);

        return res;
    }
};

时间复杂度:O(N * 2^N) 空间复杂度:O(N)

方法2:最简洁的子集模板

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
public:
    vector<int> tmp;
    vector<vector<int>> res;

    void dfs(vector<int> nums, int u) {
        res.push_back(tmp);

        for (int i = u; i < nums.size(); i ++) {
            tmp.push_back(nums[i]);
            dfs(nums, i + 1);
            tmp.pop_back();
        }
    }

    vector<vector<int>> subsets(vector<int>& nums) {
        dfs(nums, 0);
        return res;
    }
};

时间复杂度:O(N * 2^N) 空间复杂度:O(N)

方法3:位运算

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
class Solution {
public:
    vector<vector<int>> subsets(vector<int>& nums) {
        int n = nums.size();
        vector<vector<int>> res;

        for (int mask = 0; mask < (1 << n); mask ++) {
            vector<int> tmp;
            for (int i = 0; i < n; i ++) {
                if (mask & (1 << i)) {
                    tmp.push_back(nums[i]);
                }
            }
            res.push_back(tmp);
        }
        return res;
    }
};

时间复杂度:O(N * 2^N) 空间复杂度:O(N)

小结

本题有三种常见解法,回溯、位运算和迭代法(见官方题解)。