LeetCode 77 Combinations(递归、美版题解、二进制位)

题目链接:点击这里
在这里插入图片描述

递归:

class Solution {
public:
    void dfs(int start, int n, int k, vector<int>& tmp, vector<vector<int>>& ans)
    {
        if(tmp.size()==k)
        {
            ans.push_back(tmp);
            return;
        }
        for(int i = start; i <= n; i++)
        {
            tmp.push_back(i);
            dfs(i+1, n, k, tmp, ans);
            tmp.pop_back();
        }
    }

    vector<vector<int>> combine(int n, int k) {
        vector<vector<int>> ans;
        vector<int> tmp;
        dfs(1, n, k, tmp, ans);
        return ans;
    }
};

美版的题解,神来之笔:

class Solution {
public:
    vector<vector<int>> combine(int n, int k) {
        vector<vector<int>> ans;
        vector<int> b(k,0);
        int i = 0;
        while(i>=0)
        {
            b[i]++;
            if(b[i]>n)
				i--;
            else if(i==k-1)
				ans.push_back(b);
            else
            {
                i++;
                b[i] = b[i - 1];
            }
        }
        return ans;
    }
};

二进制位的角度:

预备知识:利用二进制位生成子集:点击这里

由上可知,一个子集对应一个二进制数,一个有 k k 个元素的子集,它对应的二进制数中有 k k 1 1

那么,问题就转化为查找 1 1 的个数为 k k 的二进制数,这些二进制数就是我们想要的结果。

位运算可快速判断二进制数中 1 1 的个数为 k k

  • kk = kk&(kk-1) 即清除 k k kk 中的最后一个1。连续进行这个操作可统计出 1 1 的个数。
  • 树状数组中 lowbit(x) = x & -x 功能是计算 x x 的二进制数的最后一个 1 1

在子集生成的代码基础上AC本题:

class Solution {
public:
    void print_subset(int n, int k, vector<vector<int>>& ans)
    {
        for(int i = 0; i < (1<<n); i++)
        {
            int num = 0, kk = i;    //num统计i中1的个数
            while(kk)
            {
                kk = kk&(kk-1);     //清除kk中的最后一个1
                num++;      //统计1的个数
            }
            if(num==k)      //二进制数中的1有k个,符合条件
            {
                vector<int> tmp;
                for(int j = 0; j < n; j++)
                    if(i&(1<<j))	//判断i的第j位是否为1 
                        tmp.push_back(j+1);
                ans.push_back(tmp);
            }
        }
    }

    vector<vector<int>> combine(int n, int k) {
        vector<vector<int>> ans;    //保存最后结果
        print_subset(n, k, ans);
        return ans;
    }
};
发布了701 篇原创文章 · 获赞 104 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/qq_42815188/article/details/104088904