题目:77. 组合
思路
回溯法
调试用代码
// 调试用
// 理解不了减枝那个值怎么设置的
class Solution {
private:int order = 0;vector<vector<int>> result; // 存放符合条件结果的集合vector<int> path; // 用来存放符合条件结果void backtracking(int n, int k, int startIndex) {if (path.size() == k) {result.push_back(path);return;}for (int i = startIndex; i <= n - (k - path.size()) + 1; i++) {order++;cout << order << ". ";cout << "val : " << i;cout << ", blabla : " << n - (k - path.size()) + 1 << endl;path.push_back(i); // 处理节点backtracking(n, k, i + 1); // 递归path.pop_back(); // 回溯,撤销处理的节点}}
public:vector<vector<int>> combine(int n, int k) {result.clear(); // 可以不写path.clear(); // 可以不写backtracking(n, k, 1);return result;}
};
Method 1, 剪枝 from 代码随想录
在for
循环那里,改成i <= n - (k - path.size()) + 1
;
(不好理解,人家作者也说了不好理解)
Method 2, 剪枝,自己想的
// 自己写的剪枝
class Solution {
private:vector<vector<int>> result; // 存放符合条件结果的集合vector<int> path; // 用来存放符合条件结果void backtracking(int n, int k, int startIndex) {if (path.size() == k) {result.push_back(path);return;}for (int i = startIndex; i <= n; i++) {if((k - path.size()) > (n - i + 1)) // 不够了{continue;}path.push_back(i); // 处理节点backtracking(n, k, i + 1); // 递归path.pop_back(); // 回溯,撤销处理的节点}}
public:vector<vector<int>> combine(int n, int k) {result.clear(); // 可以不写path.clear(); // 可以不写backtracking(n, k, 1);return result;}
};
增加了这部分,剩下的这部分数字(包括当前i
)比还需要找的数字数量(总共要找k
个数,已经找到了path.size()
个数字)少:
if((k - path.size()) > (n - i + 1)) // 不够了
{break;
}
比较符合我的思维,但是从效率的角度来讲可能不是最好的;(不过多一条if
语句也慢不到哪里去)
实际上经过恒等变换,是和Method 1是一样的,不过一开始就看到for
循环里,改变了遍历区间的右端确实可能转不过弯来;