77. Combinations

本文介绍了解决组合问题的两种方法:递归实现和迭代实现。递归方法通过深度优先搜索生成所有可能的组合,而迭代方法则利用STL库函数调整布尔数组来生成组合。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:组合

Given two integers n and k, return all possible combinations of k numbers out of 1 ... n.

For example,
If n = 4 and k = 2, a solution is:

[
  [2,4],
  [3,4],
  [2,3],
  [1,2],
  [1,3],
  [1,4],
]

题意:

给定两个整数n和k,返回所有由1到n之间的数构成的k个数的组合。


思路一:

递归实现。观察上面给出的例子可以看出,每个元素均需要与其之后的所有元素建立组合。则按照以上给出的例子写出代码即可。如果n=6,k=4,则组合如下所示:

1234
1235
1236
1245
1246
1256
1345
1346
1356
1456
2345
2346
2356
2456
3456

代码:C++版:136ms

class Solution {
public:
    vector<vector<int>> combine(int n, int k) {
        vector<vector<int>> res;
        vector<int> path;
        dfs(n, k, 1, 0, path, res);
        return res;
    }
private:
    //start表示开始的数。cur表示对现在有的数位进行计数,数位长度达到k位时,将单个组合放入res中
    static void dfs(int n, int k, int start, int cur, vector<int> &path, vector<vector<int>> &res) {
        if (cur == k) {
            res.push_back(path);
        }
        for (int i=start; i<=n; ++i) {
            path.push_back(i);
            dfs(n, k, i+1, cur+1, path, res);
            path.pop_back();
        }
    }
};

思路二:

迭代版。初始化一个values数组存储1到n之间的所有值,再维护一个select数组用来存储1到n中的数是否被选中,由选中的数组合成为一个组合,利用prev_permutation(select.begin(),select.end())函数调整select数组值,则代码中只需要根据select数组选择对应的数字构成组合即可。如果n=6,k=4,则组合如下所示:

value集合数组值select集合数组值one集合数组值
1234561111001234
1234561110101235
1234561110011236
1234561101101245
1234561101011246
1234561100111256
1234561011101345
1234561011011346
1234561010111356
1234561001111456
1234560111102345
1234560111012346
1234560110112356
1234560101112456
1234560011113456
由上表可以看出,values始终未变,select集合1的相同对应位置下的values数组值构成了每一个组合值。

代码:C++版:100ms

class Solution {
public:
    vector<vector<int>> combine(int n, int k) {
        vector<int> values(n);
        //将values数组初始化为1~n之间递增的数
        iota(values.begin(), values.end(), 1); //执行结果为values={1,2,3,4,5...n}
        
        vector<bool> select(n, false); //存储n个数字是否被使用
        fill_n(select.begin(), k, true); //将select数组前k个数都置为true,因为组合第一个数是依次递增的,如123..k。
        
        vector<vector<int>> result;
        do{
            vector<int> one(k); //定义一个长度为k的集合
            for (int i = 0, index = 0; i < n; ++i)
                if (select[i])
                    one[index++] = values[i]; //将初始化的123...k放入集合数组中
                result.push_back(one); //将该组合放入返回集合数组中
        } while(prev_permutation(select.begin(), select.end())); //select集合数组是否有上一个全排列
        return result;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值