From dc410fd8aa501cec3542d2c306684020d7906c4a Mon Sep 17 00:00:00 2001 From: ShusenTang Date: Mon, 22 Jun 2020 21:24:57 +0800 Subject: [PATCH] update code of solution 1 --- solutions/77. Combinations.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/solutions/77. Combinations.md b/solutions/77. Combinations.md index 653c190..87bca65 100644 --- a/solutions/77. Combinations.md +++ b/solutions/77. Combinations.md @@ -8,7 +8,7 @@ 我们建立一个保存最终结果的大集合res,还要定义一个保存每一个组合的小集合cb,每次放一个数到cb里,如果cb里数个数到了k个,则把cb保存到最终结果res中,否则在下一层中继续调用递归。 ## 思路二 -我们再来看一种递归的写法,此解法没用helper当递归函数,而是把本身就当作了递归函数,写起来十分的简洁。 +我们再来看一种递归的写法,此解法没额外定义递归函数,而是把本身就当作了递归函数,写起来十分的简洁。 这个解法用到了高中学的一个排列组合的性质:`C(n, k) = C(n-1, k-1) + C(n-1, k)`,即,在n个数中取k个数的组合项个数,等于在n-1个数中取k-1个数的组合项个数再加上在n-1个数中取k个数的组合项个数之和。 证明也很容易,因为取得的k个数可以分成两类:第一类是包含最后一个数,那么只需要在前n-1个数中再选k-1个数出来就行了,故这一类一共有`C(n-1, k-1)`种;第二类是不包含最后一个数,那么需要在前n-1个数中选k个数出来,故这一类一共有`C(n-1, k)`种。所以一共就是`C(n, k) = C(n-1, k-1) + C(n-1, k)`种。 对于题目中的例子,我们有`C(4, 2) = C(3, 1) + C(3, 2)`, 我们不难写出 C(3, 1) 的所有情况:[1], [2], [3],还有 C(3, 2) 的所有情况:[1, 2], [1, 3], [2, 3]。我们仔细看会发现,C(3, 2)的所有情况包含在 C(4, 2) 之中,但是 C(3, 1) 的每种情况只有一个数字,而我们需要的结果k=2,其实很好办,每种情况后面都加上4,于是变成了:[1, 4], [2, 4], [3, 4],加上C(3, 2) 的所有情况:[1, 2], [1, 3], [2, 3],正好就得到了 n=4, k=2 的所有情况了。 @@ -21,23 +21,23 @@ ``` C++ class Solution { private: - void helper(vector> &res, vector &cb, const int level, const int n, const int k){ + void DFS(vector> &res, vector &cb, int start, int n, int k){ if(cb.size() == k){ res.push_back(cb); return; } - for(int i = level; i <= n; i++){ - cb.push_back(i); - helper(res, cb, i + 1, n, k); - cb.pop_back(); - } + if(start > n) return; + + DFS(res, cb, start + 1, n, k); + cb.push_back(start); + DFS(res, cb, start + 1, n, k); + cb.pop_back(); } public: vector> combine(int n, int k) { vector>res; vectorcb; - if(n < k) return res; - helper(res, cb, 1, n, k); + DFS(res, cb, 1, n, k); return res; } };