zoukankan      html  css  js  c++  java
  • 子集生成

    问题:输出$[0,1,2,3,...n)$的所有子集。

    1. 增量构造法:一次选出一个元素放到集合中。由于$A$中的元素个数不确定,每次递归调用都要输出当前集合。另外,递归边界也不需要显示确定——如果无法继续添加元素,自然就不会递归了。

    void print_subset(int n, int* A, int cur){
        for(int i = 0; i < cur; i++) printf("%d ", A[i]);
        printf("
    ");
        int s = cur ? A[cur - 1] + 1 : 0;
        for(int i = s; i < n; ++i){
            A[cur] = i;
            print_subset(n, A, cur + 1);
        }
    }

    2. 位向量法:构造一个位向量$B[i]$,而不是直接构造子集$A$本身,其中$B[i]=1$,当且仅当$i$在子集$A$中。

    void print_subset1(int n, int* B, int cur){
        if(cur == n){
            for(int i = 0; i < cur; ++i)
                if(B[i]) printf("%d ", i);
            printf("
    ");
            return;
        }
        B[cur] = 1;
        print_subset1(n, B, cur + 1);
        B[cur] = 0;
        print_subset1(n, B, cur + 1);
    }

    3. 二进制法:当用二进制表示子集时,位运算中的按位与、或、异或对应集合的交、并和对称差。

    输出子集$S$对应的各个元素:

    void print_subset2(int n, int s){
        for(int i = 0; i < n; ++i)
            if(s & (1 << i)) printf("%d ", i);
        printf("
    ");
    }

    枚举子集:

    for(int i = 0; i < (1 << n); ++i)
            print_subset2(n, i);

     Leetcode 78. Subsets

    给一个包含不同整数的集合,返回其所有子集。

    方法1:(recursive)

    class Solution {
    public:
        vector<vector<int>> subsets(vector<int>& nums) {
            vector<vector<int>> subs;
            vector<int> sub;
            dfs(nums, 0, sub, subs);
            return subs;
        }
        
        void dfs(vector<int>& nums, int i, vector<int>& sub, vector<vector<int>>& subs){
            subs.push_back(sub);
            for(int j = i; j < nums.size(); ++j){
                sub.push_back(nums[j]);
                dfs(nums, j + 1, sub, subs);
                sub.pop_back();
            }
        }
    };

    方法2:位运算

    class Solution {
    public:
        vector<vector<int>> subsets(vector<int>& nums) {
            int n = nums.size();
            vector<vector<int>> res;
            for(int i = 0; i < (1 << n); ++i){
                vector<int> cur;
                for(int j = 0; j < n; ++j){
                    if(i & (1 << j))
                        cur.push_back(nums[j]);
                }
                res.push_back(cur);
            }
            return res;
        }
    };

     方法3:(iterative)

    class Solution {
    public:
        vector<vector<int>> subsets(vector<int>& nums) {
            vector<vector<int>> subs = {{}};
            for (int num : nums) {
                int n = subs.size();
                for (int i = 0; i < n; i++) {
                    subs.push_back(subs[i]); 
                    subs.back().push_back(num);
                }
            }
            return subs;
        }
    }; 

     Leetcode 90. Subsets II

    给定一个集合,包含重复元素,返回其所有子集。

    方法1:(iterative)

    class Solution {
    public:
        vector<vector<int>> subsetsWithDup(vector<int>& nums) {
            sort(nums.begin(), nums.end());
            vector<vector<int>> res = {{}};
            for(int i = 0; i < nums.size();){
                int cnt = 0, num = nums[i];
                while(i < nums.size() && nums[i] == num){
                    i++;
                    cnt++;
                }
                int size = res.size();
                for(int j = 0; j < size; ++j){
                    vector<int> tmp = res[j];
                    for(int k = 0; k < cnt; ++k){
                        tmp.push_back(num);
                        res.push_back(tmp);
                    }
                }
            }
            return res;
        }
    };

     方法2:(recursive)

    class Solution {
    public:
        vector<vector<int>> subsetsWithDup(vector<int>& nums) {
            sort(nums.begin(), nums.end());
            vector<vector<int>> subs;
            vector<int> sub;
            dfs(subs, sub, nums, 0);
            return subs;
        }
        
        void dfs(vector<vector<int>>& subs, vector<int>& sub, vector<int>& nums, int i){
            subs.push_back(sub);
            for(int j = i; j < nums.size(); ++j){
                if(j == i || nums[j] != nums[j - 1]){
                    sub.push_back(nums[j]);
                    dfs(subs, sub, nums, j + 1);
                    sub.pop_back();
                }
            }
        }
    };
  • 相关阅读:
    mvn package打包提示:Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources
    [Android] 【手机定位他迹】最新破解版 ,解锁VIP会员,去除广告绿化等等
    Python编程:从入门到实践超清版及全书源代码
    Win11永久激活工具 (可激活win10) + 注册码+Win11 正式版发布 版本号22000.194
    通过命令为 Elementary OS 窗口添加最小化按钮
    inno setup 通过指针获取完整字符串(宽字节字符)
    竹子开花
    屋后有靠山生万福
    自然吸气和涡轮增压哪个好 按需选择是关键
    父母对钱的态度,影响孩子的一生
  • 原文地址:https://www.cnblogs.com/betaa/p/11686111.html
Copyright © 2011-2022 走看看