leetcode 77. 组合

问题描述

给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合。

示例:

输入: n = 4, k = 2
输出:
[
  [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>> ans;
        vector<int> path;
        backtrack(1,k,n,path,ans);
        return ans;
    }
    void backtrack(int fir,int k,int n,vector<int> &path,vector<vector<int>> &ans)
    {
        if(path.size() == k)
        {
            ans.push_back(path);//满足路径长度,则返回
            return;
        }
        for(int i = fir; i <= n ; ++i)
        {
            path.push_back(i);
            backtrack(i+1,k,n,path,ans);
            path.pop_back();
        }
    }
};

结果

执行用时 :184 ms, 在所有 cpp 提交中击败了32.03%的用户
内存消耗 :11.7 MB, 在所有 cpp 提交中击败了83.64%的用户

我们来看看为什么for循环中的i <= n可以替换为i <= n - (k - path.size()) + 1,我们通过几个例子来说明,如果取n = 6,k = 4:

  • path.size() == 1,则path中能加3个元素,这时i最大可取4,因为i > 4后就凑不齐3个元素无解了;
  • path.size() == 2,则path中能加2个元素,这时i最大可取5,因为i > 5后就凑不齐2个元素无解了;
  • path.size() == 3,则path中能加1个元素,这时i最大可取6,因为i > 6后就凑不齐1个元素无解了;

通过上面观察可以知道i不必遍历到n,能添加的元素个数为k - path.size(),设能添加的最大元素是m,则m满足m + k - path.size() = n + 1(3+4=2+5=1+6=7),因此m = n + 1 - (k - path.size()).

//剪枝代码
class Solution {
public:
    vector<vector<int>> combine(int n, int k) {
        vector<vector<int>> ans;
        vector<int> path;
        backtrack(1,k,n,path,ans);
        return ans;
    }
    void backtrack(int fir,int k,int n,vector<int> &path,vector<vector<int>> &ans)
    {
        if(path.size() == k)
        {
            ans.push_back(path);//满足路径长度,则返回
            return;
        }
        for(int i = fir; i <= n - (k - path.size()) + 1; ++i)
        {
            path.push_back(i);
            backtrack(i+1,k,n,path,ans);
            path.pop_back();
        }
    }
};

结果

执行用时 :76 ms, 在所有 cpp 提交中击败了97.21%的用户
内存消耗 :11.8 MB, 在所有 cpp 提交中击败了76.95%的用户
posted @ 2020-03-04 20:35  曲径通霄  阅读(242)  评论(0编辑  收藏  举报