zoukankan      html  css  js  c++  java
  • 77. Combinations

    Problem:

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

    Example:

    Input: n = 4, k = 2
    Output:
    [
      [2,4],
      [3,4],
      [2,3],
      [1,2],
      [1,3],
      [1,4],
    ]
    

    思路
    这题的思路很难直接用语言表述,建议看代码,然后再纸上将其每一步运行的结果一步步写出,就好理解了。
    大致的思路是这样的,它是按照从右往左来试探的。首先确定好低位之后,最高位的值如果不超过n(高位低位以数组的下标来理解)则满足条件。如果最高位的值超过n,则说明次高位的值还有增加的空间,调整次高位的值(++),再让最高位的值等于次高位的值然后依次往上递增,看是否满足条件。如果较高位的值都超过了n,则会一直往低位去寻找,如果每一位的值都超过了n,那么最好寻找的下标i会小于0,从而不满足while循环的条件,循环终止,重新开始。

    Solution:

    vector<vector<int>> combine(int n, int k) {
        vector<vector<int>> res;
        int i = 0;
        vector<int> p(k, 0);
            
        while (i >= 0) {
            p[i]++;
            if (p[i] > n) 
                 --i;
            else if (i == k-1) 
                res.push_back(p);
            else {
                ++i;
                p[i] = p[i-1];
            }
        }
            
        return res;            
    }
    

    性能
    Runtime: 76 ms  Memory Usage: 11.8 MB

    扩展
    有兴趣的同学可以运行下面的代码(来自于LeetCode)来理解上面代码的思路,验证流程是否正确,确实挺佩服老外的钻研精神。

    #include <iostream>
    #include <vector>
    #include <string>
    
    using namespace std;
    
    string toString(vector<int> v) {
        string ans = "[";
        for (int i: v) {
            ans += i + '0';
            ans += ", ";
        }
        ans = ans.substr(0, ans.length() - 2) + "]";
        return ans;
    }
    
    string toString(vector<vector<int>> v) {
        string ans = "[";
        for (vector<int> i: v) {
            ans += toString(i);
            ans += ", ";
        }
        ans = ans.substr(0, ans.length() - 2) + "]";
        return ans;
    }
    
    class Solution {
    public:
        vector<vector<int>> combine(int n, int k) {
            vector<vector<int>> ans;
            vector<int> c(k, 0); // vector of length k, all 0s
            int i = 0;
            while (i >= 0) {
                // Increment element at index i
                c[i]++;
                cout << "Incremented element at index " << i << endl;
                cout << toString(c) << endl;
                
                /* Move index to the left if the element
                 * at index i has exceeded n.
                 */
                if (c[i] > n) {
                    i--;
                    cout << "n exceeded at " << i+1 << ", moving index to the left" << endl;
                }
                
                /* If the index is at the end of the vector
                 * c, then (because the other conditions are
                 * obeyed), we know we have a valid combination,
                 * so push it to our ans vector<vector<>>
                 */
                else if (i == k - 1) {
                    ans.push_back(c);
                    cout << "Combination found!" << endl;
                    cout << "Added " << toString(c) << " as an answer!" << endl;
                }
                
                /* Move index to the right and set the
                 * element at that index equal to the
                 * element at the previous index.
                 * 
                 * Because of the increment at the beginning
                 * of this while loop, we ensure that the
                 * element at this index will be at least
                 * one more than its neighbor to the left.
                 */
                else {
                    i++;
                    c[i] = c[i - 1];
                    cout << "Moved index to the right, and copied the value"
                    << " from the left" << endl;
                    cout << toString(c) << endl;
                }
            }
            return ans;
        }
    };
    
    int main() {
        Solution sol;
        cout << toString(sol.combine(4, 2)) << endl;
        return 0;
    }
    
    相关链接如下:

    知乎:littledy

    欢迎关注个人微信公众号:小邓杂谈,扫描下方二维码即可

    作者:littledy
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利。
  • 相关阅读:
    Linux下取代top的进程管理工具 htop
    Linux学习初步
    【程序员的吐槽】八一八那些让你感觉蠢哭了的BUG
    【学习随手记】POSIX消息队列执行报Permission denied的问题。
    【学习总结】环境高级编程源码配置
    【学习总结】UNIX网络编程使用源码配置
    【工作心得】有关主键索引
    【转】More Effective C++ (虚拟构造函数)
    【转】C++ 类中特殊的成员变量(常变量、引用、静态)的初始化方法
    【学习心得】python学习心得
  • 原文地址:https://www.cnblogs.com/dysjtu1995/p/12250987.html
Copyright © 2011-2022 走看看