【LeetCode】78。サブセット(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)

再帰を行うときは、再帰に沿って徐々に次のレイヤーにジャンプし、midArrayの配列を維持し、再帰の開始時に結果に直接配置するのではなく、問題を実行するという全体的な考え方を理解する必要があります、次に、次の要素を追加します。次に、再帰に移動し、ループに従って現在の番号のすべてのサブセットをプッシュし、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であるため、元の配列のどの要素が含まれているかを示すために2進数を使用することは簡単に考えられます。すべてのサブセット、0/1シーケンスの場合010(1 << 2)でマスクビットの場合、現在の最後から2番目のビットが1であると判断され、一時配列の温度をプッシュする必要があります(nums [1])。同様に、111、現在のマスクビットは1であり、temp.pushをループし、最後にそれをansに入れます。

0/1シーケンス 子集 0/1シーケンスに対応する2進数(マスク)
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