本文主要是介绍重拾C++之菜鸟刷算法第11篇---回溯算法(上),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
今天是个好日子,二月二龙抬头,龙年龙日龙抬头,顺风顺水好兆头,万事万物开好头,金银珠宝往家里走!offer往家走!
回溯算法
回溯法可以解决的问题
- 组合问题:N个数里面按照一定规则找出k个数的集合
- 切割问题:一个字符串按一定规则有几种切割方式
- 子集问题:一个N个数的集合里有多少符合条件的子集
- 排列问题:N个数按一定规则全排列,有几种排列方式
- 棋盘问题:N皇后,解数独
回溯三部曲
- 回溯函数模板返回值以及参数
- 回溯函数终止条件
- 回溯搜索的遍历过程
void backtracking(参数){if(终止条件){存放结果;return;}for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)){backtracking(路径,选择列表); // 递归回溯,撤销处理结果}}
组合
for循环横向遍历,递归纵向遍历,回溯不断调整结果集。
题目
给定两个整数 n
和 k
,返回范围 [1, n]
中所有可能的 k
个数的组合。
你可以按 任何顺序 返回答案。
77. 组合 - 力扣(LeetCode)
题解
class Solution {
public:// 创建一个全局变量来放pathvector<int> path;// 创建一个全局变量来放所有的pathvector<vector<int>> result;void backtracking(int n, int k, int startIndex){if(path.size() == k){result.push_back(path);return;}for(int i = startIndex; i <= n; i++){// 处理节点path.push_back(i);backtracking(n, k, i + 1);// 回撤,撤销处理节点path.pop_back();}}vector<vector<int>> combine(int n, int k) {backtracking(n, k, 1);return result;}
};
可以剪枝的地方在递归中每一层的for循环所选择的位置,比如说for循环选择的起始位置之后的元素个数已不足k个,那么就没有必要再进行for循环
组合总和III
题目
找出所有相加之和为 n
的 k
个数的组合,且满足下列条件:
- 只使用数字1到9
- 每个数字 最多使用一次
返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。
216. 组合总和 III - 力扣(LeetCode)
题解
class Solution {
public:vector<int> path;vector<vector<int>> result;void backtracking(int n, int k, int startIndex){if(path.size() == k){ if (accumulate(path.begin(), path.end(), 0) == n) result.push_back(path);else return;}for(int i = startIndex; i <= 9; i++){path.push_back(i);backtracking(n, k, i + 1);path.pop_back();}}vector<vector<int>> combinationSum3(int k, int n) {backtracking(n, k, 1);return result;}
};
电话号码的字母组合
题目
给定一个仅包含数字 2-9
的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
17. 电话号码的字母组合 - 力扣(LeetCode)
题解
index:是记录遍历第几个数字了,就是用来遍历digits的(题目中给出数字字符串),同时index也表示树的深度。
class Solution {
public:vector<string> result;string path;void backtracking(const string &digits, int index){if(index == digits.size()){result.push_back(path);return;}int digit = digits[index] - '0';string letters = letterMap[digit];for(int i = 0; i < letters.size(); i++){path.push_back(letters[i]);backtracking(digits, index + 1);path.pop_back();}}vector<string> letterCombinations(string digits) {if(digits.size() == 0) return result;backtracking(digits, 0);return result;}
private:const string letterMap[10] = {"", //0"", //1"abc", //2"def", //3"ghi", //4"jkl", //5"mno", //6"pqrs", //7"tuv", //8"wxyz", // 9};
};
这篇关于重拾C++之菜鸟刷算法第11篇---回溯算法(上)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!