【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();
            }
        }
};
原文地址:https://www.cnblogs.com/xbf9xbf/p/4520749.html