【LeetCode】78. 子集 Subsets(C++)


题目来源:https://leetcode-cn.com/problems/subsets/

题目描述

给你一个整数数组nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。

示例 1:

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

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

提示:
1 <= nums.length <= 10
-10 <= nums[i] <= 10
nums 中的所有元素 互不相同

题目大意

在一个数组中,返回所有的子集,包括空集合,本题如果用暴力法来做,会导致时空复杂度过大,且过程复杂,能直接想到的方法有迭代法和递归(或dfs)来做

递归(dfs)

在做递归的时候需要理解整体做题的思路,而不是顺着递归逐渐跳到下一层,维护一个midArrays数组,在递归的开始就直接将他放进结果ans里,然后添加下一个元素,然后再进到递归,跟着循环将当前数的子集全部push完,然后再pop_back再把最后一个元素给删了,再根据边界条件i∈[0,nums.size),最终ans中的所有元素就是当前数组的所有子集

class Solution {
    
    
public:
    vector<vector<int>> subsets(vector<int>& nums) {
    
    
        int len = nums.size();
        vector<int> temp;
        vector<vector<int>> ans;
        subsets(nums, 0, temp, ans);
        return ans;
    }
    void subsets(vector<int> nums, int index, vector<int>& midArrays, vector<vector<int>>& ans){
    
    
        ans.push_back(midArrays);
        for(int i = index ; i < nums.size(); ++i){
    
    
            midArrays.push_back(nums[i]);
            subsets(nums, i + 1, midArrays, ans);
            midArrays.pop_back();
        }
    }
};

复杂度分析

  • 时间复杂度:O(n*2^n)。总共有2^n个子集,每个子集需要O(n)的时间构建
  • 空间复杂度:O(n)。临时数组O(n),递归栈空间为O(n)

迭代

假设num[] = [1,2,3],可找到以下规律,由于子集数是2^n个,容易想到使用二进制数去表示所有子集包含原数组的哪些元素,当0/1序列为010时(1<<2)与mask位与,判断当前倒数第二位为1,那么此时临时数组temp应push(nums[1]),同理111则当前mask各个位为1,循环temp.push,最终再放入到ans中

0/1序列 子集 0/1序列对应的二进制数(mask)
000 [] 0
001 [1] 1
010 [2] 2
011 [1,2] 3
100 [3] 4
101 [1,3] 5
110 [2,3] 6
111 [1,2,3] 7

AC代码

class Solution {
    
    
public:
    vector<vector<int>> subsets(vector<int>& nums) {
    
    
        int len = nums.size();
        vector<int> temp;
        vector<vector<int>> ans;
        for(int mask = 0; mask < (1 << len) ; ++mask){
    
    
            temp.clear();
            for(int j = 0 ; j < len ; ++j){
    
    
                if(mask & (1 << j)){
    
    
                    temp.push_back(nums[j]);
                }
            }
            ans.push_back(temp);
        }
        return ans;
    }
};

复杂度分析

  • 时间复杂度:O(n*2^n)。双重循环,外层循环次数为2^n,里面为[0,n)的循环
  • 空间复杂度:O(n)。临时数组O(n)

猜你喜欢

转载自blog.csdn.net/lr_shadow/article/details/113934454