今天学习了回溯的算法。
先记录一下模板:
void backtracking(参数) { if (终止条件) { 存放结果; return; } for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) { 处理节点; backtracking(路径,选择列表); // 递归 回溯,撤销处理结果 } }
77. 组合 - 力扣(LeetCode) (leetcode-cn.com)
递归来做层叠嵌套(可以理解是开k层for循环),**每一次的递归中嵌套一个for循环,那么递归就可以用于解决多层嵌套循环的问题了**。
剪枝优化:
**所以,可以剪枝的地方就在递归中每一层的for循环所选择的起始位置**。
**如果for循环选择的起始位置之后的元素个数 已经不足 我们需要的元素个数了,那么就没有必要搜索了**。
注意代码中i,就是for循环里选择的起始位置。
for (int i = startIndex; i <= n; i++) {接下来看一下优化过程如下:
已经选择的元素个数:path.size();
还需要的元素个数为: k - path.size();
在集合n中至多要从该起始位置 : n - (k - path.size()) + 1,开始遍历
为什么有个+1呢,因为包括起始位置,我们要是一个左闭的集合。
class Solution { public: vector> result; vector 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++) { // 优化的地方 path.push_back(i); // 处理节点 backtracking(n, k, i + 1); path.pop_back(); // 回溯,撤销处理的节点 } } vector > combine(int n, int k) { backtracking(n, k, 1); return result; } };
46. 全排列 - 力扣(LeetCode) (leetcode-cn.com)
套模板解题
class Solution { public: vector>result; vector path; void backtracking(vector &nums,int k,vector &vistited){ if(path.size()==k) { result.push_back(path); return; } int w=0; for(int i=0;i > permute(vector & nums) { vector vistited(nums.size(),false); backtracking(nums,nums.size(),vistited); return result; } };
784. 字母大小写全排列 - 力扣(LeetCode) (leetcode-cn.com)
class Solution { private: vectorresult; public: void back(string &s, int i){ if(i==s.size()){ result.emplace_back(s); return ; } if(isdigit(s[i])){ back(s, i+1); } else{ s[i]=tolower(s[i]); back(s, i+1); s[i]=toupper(s[i]); back(s, i+1); } } vector letterCasePermutation(string s) { back(s, 0); return result; } };
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)