【Combinations】cpp

题目:

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],
]

代码:

复制代码
class Solution {
public:
    vector<vector<int>> combine(int n, int k) {
            vector<vector<int> > ret;
            if ( n<k ) return ret;
            vector<int> tmp;
            Solution::dfs(ret, 1, k, n, 0,tmp);
            return ret;    
    }
    static void dfs(vector<vector<int> >& ret, int index, int k, int n, int step, vector<int>& tmp)
    {
            if ( step==k )
            {
                ret.push_back(tmp);
                return;
            }
            for ( size_t i = index; i <=n; ++i )
            {
                tmp.push_back(i);
                Solution::dfs(ret, i+1, k, n, step+1, tmp);
                tmp.pop_back();
            }
    }
};
复制代码

tips:

dfs解法。

几个参数的含义:

ret: 存储返回combination结果

index: 当前起始元素是多大

k,n:与题意所给相同

step:深入到第几层

思路:dfs的每层增加一个元素,直到深度等于k返回结果;如果从index开始的元素不足以打到深度k,则不会添加到ret中。

======================================

其实,可以不用传入6个参数,传入5个足以。代码如下:

复制代码
class Solution {
public:
    vector<vector<int>> combine(int n, int k) {
            vector<vector<int> > ret;
            if ( n<k ) return ret;
            vector<int> tmp;
            Solution::dfs(ret, 1, k, n, tmp);
            return ret;    
    }
    static void dfs(vector<vector<int> >& ret, int index, int k, int n, vector<int>& tmp)
    {
            if ( tmp.size()==k )
            {
                ret.push_back(tmp);
                return;
            }
            for ( size_t i = index; i <=n; ++i )
            {
                tmp.push_back(i);
                Solution::dfs(ret, i+1, k, n, tmp);
                tmp.pop_back();
            }
    }
};
复制代码

用tmp.size()代替step,代码跟简洁一些,因此更推崇后一种方法。

=======================================

leetcode写到这里有些感觉了,搜了一下dfs bfs的模板相关的内容,基本跟实战中的经验差不多:

http://blog.csdn.net/fightforyourdream/article/details/12866861

http://www.cnblogs.com/HectorInsanE/archive/2010/11/09/1872656.html

=======================================

再补上一种迭代的解法,如下:

复制代码
class Solution {
public:
    vector<vector<int>> combine(int n, int k) {
            vector<vector<int> > ret;
            // corner cases
            if ( n<k || k==0 ) return ret;
            // initialization
            for ( int i = 0; i < n-k+1; ++i ) 
            {
                vector<int> tmp;
                tmp.push_back(i+1);
                ret.push_back(tmp);
            }
            // combines
            for ( int i = 0; i < k-1; ++i )
            {
                vector<vector<int> > tmp = ret;
                ret.clear();
                for ( int j = 0; j < tmp.size(); ++j )
                {
                    int curr = tmp[j].back();
                    for ( int v = curr+1; v <= n; ++v )
                    {
                        vector<int> ori = tmp[j];
                        ori.push_back(v);
                        ret.push_back(ori);
                    }
                }
            }
            return ret;    
    }
};
复制代码

tips:

1. 这种迭代方式返回的组合内部都是由小到大排序的。

2. intialization的含义是”组合首个元素最小到最大“(比如n=4,k=2 按照原则1,则首个元素最大取到3,因为比4小的元素没有了不足以满足k=2的条件)

3. 每轮迭代,先取出来当前组合最后一个元素(最大的)curr;再从curr+1到n挨个取值,补到tmp[j]的后面,构成新的组合。

4. 控制迭代的次数是k-1次(因为initialization已经算了一次)

===============================================

 第二次过这道题,用dfs过的,传入参数比第一次过更简洁一些。

复制代码
class Solution {
public:
        vector<vector<int> > combine(int n, int k)
        {
            vector<vector<int> > ret;
            vector<int> tmp;
            Solution::dfs(ret, tmp, n, k);
            return ret;
        }
        static void dfs(
            vector<vector<int> >& ret, 
            vector<int>& tmp, 
            int n, int k)
        {
            if ( tmp.size()==k )
            {
                ret.push_back(tmp);
                return;
            }
            int index = tmp.empty() ? 0 : tmp.back();
            for ( int i=index+1; i<=n; ++i )
            {
                tmp.push_back(i);
                Solution::dfs(ret, tmp, n, k);
                tmp.pop_back();
            }
        }
};
复制代码

 

posted on   承续缘  阅读(190)  评论(0编辑  收藏  举报

编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示