首页 > 编程语言 >backtrack-回溯搜索算法总结

backtrack-回溯搜索算法总结

时间:2023-02-20 23:55:33浏览次数:32  
标签:nums int res backtrack back 搜索算法 vector 回溯 path

backtrack-回溯搜索算法总结

到底什么是回溯?

回溯算法,都知道是基于递归的算法。那为什么要用递归呢,可以用传统的写法代替嘛?之所以用递归,就是因为如果用传统的方式,很难写或者根本写不出来。举个例子,比如我们想知道用集合nums = [1, 2, 3]中的三个数字(可重复)一共能构成多少个不同的三位数,学过排列组合的都知道一共有27(3的3次方)种:(1,1,1), (1,1,2), (1,1,3), (2,1,1), (2,1,2), (2,1,3)…(3,3,3) 。用最传统的方式,都会写,用一个三层的for循环来写:

vector<vector<int>> res;
vector<int> path;
for (int i = 0; i < 3; i++) {
	for (int j = 0; j < 3; j++) {
	 	for (int k = 0; k < 3; k++) {
	 		path.push_back({ nums[i], nums[j], nums[k] });
	 		res.push_back(path);
	 	}
	 }
}

这个例子中,集合中的元素还很少。那么如果集合中有100个元素呢?传统方式是不是要写100层循环?1000呢?因此,这种情况下单靠循环是完成不了的。这种情况下,就需要递归出场了。上面的代码可以写为如下递归的形式:

vector<vector<int>> res;
vector<int> path;
void backtrack_0(vector<int>& nums,  vector<vector<int>> &res) {
	if (path.size() == nums.size()) {
		res.push_back(path);
		return;
	}
	// else
	for (int i = 0; i < nums.size(); i++) {
		path.push_back(nums[i);
		backtrack_0(nums, res);
		path.pop_back();
	}
}

上面的代码中,path的长度其实就是循环的深度,回溯递归里的每一层其实都是一个循环;而else部分,则相当于每层循环的方式(每层for循环该怎么写)。递归其实就模拟了上述过程。

如果题目变成了三个数字加起来能构成不同的和的情况有多少(就是前面用过的数,后面不能再用。比如:112和211的和就是一样的)?那么该怎么改呢?
传统的写法:

for (int i = 0; i < 3; i++) {
	for (int j = i; j < 3; j++) {
	 	for (int k = j; k < 3; k++) {
	 		path.push_back({ nums[i], nums[j], nums[k] });
	 		res.push_back(path);
	 	}
	 }
}

对应的递归写法:

vector<vector<int>> res;
vector<int> path;
void backtrack_1(vector<int>& nums,  vector<vector<int>> &res, int idx) {
	if (path.size() == nums.size()) {
		res.push_back(path);
		return;
	}
	// else
	for (int i = idx; i < nums.size(); i++) {
		path.push_back(nums[i);
		backtrack_1(nums, res, i);
		path.pop_back();
	}
}

最后的输出都一样:[1, 1, 1], [1, 1, 2], [1, 1, 3], [1, 2, 2], [1, 2, 3], [1, 3, 3], [2, 2, 2], [2, 2, 3], [2, 3, 3], , [3, 3, 3]。
同时,从这里可以看到:循环的起始范围变了:从0变成了上层循环的循环变量;而在回溯函数中,循环的起始值也从0变为了idx。说明,回溯跟多层循环有着非常密切的关系!终止条件跟循环层数有关系,递归函数里面的循环跟每层循环又有着非常紧密的联系!

标签:nums,int,res,backtrack,back,搜索算法,vector,回溯,path
From: https://www.cnblogs.com/bujidao1128/p/17139466.html

相关文章

  • 深度优先搜索算法-dfs讲解
    迷宫问题有一个迷宫:S**.....***T(其中字符S表示起点,字符T表示终点,字符*表示墙壁,字符.表示平地。你需要从S出发走到T,每次只能向上下左右相邻的位置移动,不能走出地图,也......
  • 基于Astar算法的栅格地图目标最短路径搜索算法MATLAB仿真,带GUI界面
    1.算法描述Astar算法是一种图形搜索算法,常用于寻路。它是个以广度优先搜索为基础,集Dijkstra算法与最佳优先(bestfit)算法特点于一身的一种算法。它通过下面这个函数来......
  • 基于Astar算法的栅格地图目标最短路径搜索算法MATLAB仿真,带GUI界面
    1.算法描述       Astar算法是一种图形搜索算法,常用于寻路。它是个以广度优先搜索为基础,集Dijkstra算法与最佳优先(bestfit)算法特点于一身的一种算法。它通过......
  • LeetCode回溯算法
    回溯模板1privatevoidbacktrack("原始参数"){2//终止条件(递归必须要有终止条件)3if("终止条件"){4//一些逻辑操作(可有可无,视情况而定)......
  • 搜索与回溯算法笔记
    目录搜索与回溯算法  迷宫问题:例5.1素数环:将1到20这20个数摆成一个环,要求相邻的两个数的和是一个素数。例5.2:设有n个整数的集合{1,2,……,n},从中任意取出r个数进行排列(r<n),试......
  • LeetCode 组合总和(/回溯+剪枝)
    原题解题目约束题解不剪枝classSolution{public:voiddfs(vector<int>&candidates,inttarget,vector<vector<int>>&ans,vector<int>&combine,......
  • 算法导论:回溯法
    基本思想将所有的解按照一定结构排列,再进行搜索。一般解空间构造成树状结构,用深度优先搜索策略。针对所给问题,定义问题的解空间。确定易于搜索的解空间结构。以深度优......
  • 代码随想录算法训练营第二十四天 | 第七章 回溯算法-理论基础,77. 组合
    一、参考资料理论基础题目链接/文章讲解:https://programmercarl.com/%E5%9B%9E%E6%BA%AF%E7%AE%97%E6%B3%95%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html视频讲解:htt......
  • 搜索与回溯 自然数的拆分
    【例5.3】自然数的拆分时间限制:1000ms      内存限制:65536KB提交数:687   通过数:427 【题目描述】任何一个大于1的自然数n,总可以拆分成若干个小于n的......
  • 搜素与回溯 素数环:
    素数环:从1到20这20个数摆成一个环,要求相邻的两个数的和是一个素数。书上算法分析:【算法分析】非常明显,这是一道回溯的题目。从1开始,每个空位有20种可能,只要填进去的数合法:......