【LetMeFly】216.组合总和 III:回溯(剪枝) OR 二进制枚举 力扣题目链接:https://leetcode.cn/problems/combination-sum-iii/
找出所有相加之和为 n
的 k
个数的组合,且满足下列条件:
返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。
示例 1:
输入: k = 3, n = 7
输出: [[1,2,4]]
解释:
1 + 2 + 4 = 7
没有其他符合的组合了。
示例 2:
输入: k = 3, n = 9
输出: [[1,2,6], [1,3,5], [2,3,4]]
解释:
1 + 2 + 6 = 9
1 + 3 + 5 = 9
2 + 3 + 4 = 9
没有其他符合的组合了。
示例 3:
输入: k = 4, n = 1
输出: []
解释: 不存在有效的组合。
在[1,9]范围内使用4个不同的数字,我们可以得到的最小和是1+2+3+4 = 10,因为10 > 1,没有有效的组合。
提示:
方法一:二进制枚举(选与不选) 一共$9$个数,每个数选与不选一共有$2^9=512$种情况。
我们只需要使用一个二进制数一一枚举这$512$种情况即可。
二进制数的每一位代表每个数的选与不选,对于某种情况,只需要判断是否恰好为$k$个数,以及是否恰好和为$n$即可。
时间复杂度$O(C\times2^C)$,其中$C=9$
空间复杂度$O(C)$
AC代码 C++ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class Solution {public : vector<vector<int >> combinationSum3 (int k, int n) { vector<vector<int >> ans; int to = 1 << 9 ; for (int i = 0 ; i < to; i++) { if (__builtin_popcount(i) != k) { continue ; } vector<int > thisSolution; int thisCnt = 0 ; for (int j = 0 ; j < 9 ; j++) { if (i & (1 << j)) { thisCnt += j + 1 ; thisSolution.push_back (j + 1 ); } } if (thisCnt == n) { ans.push_back (thisSolution); } } return ans; } };
Python 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Solution : def combinationSum3 (self, k: int , n: int ) -> List [List [int ]]: ans = [] for i in range (1 << 9 ): if i.bit_count() != k: continue thisSolution = [] thisCnt = 0 for j in range (9 ): if i & (1 << j): thisCnt += j + 1 thisSolution.append(j + 1 ) if thisCnt == n: ans.append(thisSolution) return ans
方法二:回溯+剪枝(DFS) 写一个函数dfs(k, n, index)
来求所有“从[index,9]范围内选k个数使得和为n”的情况。
如果k = 0 && n == 0
,则说明当前方案为一个可行方案,计入答案中且返回
如果index > n || index == 10 || k <= 0
,则终止(剪枝/递归终止条件)
这样,就只有选与不选index
这两种情况:
不选index
:直接递归调用dfs(k, n, index + 1)
选index
:将index
加入当前选择方案的数组中、递归调用dfs(k - 1, n - index, index + 1)
、将index
从当前方案中移除(回溯)
以上
时间复杂度$O(\begin{pmatrix}C\ k\end{pmatrix}\times k)$,其中$C=9$,$\begin{pmatrix}C\ k\end{pmatrix}$为组合数从$C$个数里面选$k$个
空间复杂度$O(C)$
AC代码 C++ 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 class Solution {private : vector<vector<int >> ans; vector<int > now; void dfs (int k, int n, int index) { if (!k && !n) { ans.push_back (now); return ; } if (index > n || index == 10 || k <= 0 ) { return ; } dfs (k, n, index + 1 ); now.push_back (index); dfs (k - 1 , n - index, index + 1 ); now.pop_back (); }public : vector<vector<int >> combinationSum3 (int k, int n) { dfs (k, n, 1 ); return ans; } };
小数据情况下,方法一 的实际执行效果也许会优于方法二 。
Python 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Solution : def dfs (self, k: int , n: int , index: int ) -> None : if not k and not n: self .ans.append(self .now[:]) return if index > n or index == 10 or k <= 0 : return self .dfs(k, n, index + 1 ) self .now.append(index) self .dfs(k - 1 , n - index, index + 1 ) self .now.pop() def combinationSum3 (self, k: int , n: int ) -> List [List [int ]]: self .ans = [] self .now = [] self .dfs(k, n, 1 ) return self .ans
同步发文于CSDN和我的个人博客 ,原创不易,转载经作者同意后请附上原文链接 哦~ Tisfy:https://letmefly.blog.csdn.net/article/details/138033273