2020年2月23日
1.什么是递归?
任何调用自身的函数称为递归。用递归方法求解问题,要点在于递归函数调用自身 去解决一个规模比原始问题小一些的问题。这个过程称为递归步骤。递归步骤会导致更 多的递归调用。因此,保证递归过程能够终止是很重要的。每次函数都会用比原问题规 模更小的问题来调用自身。问题随着规模不断变小必须能最终收敛到基本情形。
2.为什么要用递归
递归是从数学领域借鉴过来的一种有用的技术。递归代码通常比迭代代码更加简洁 易慷。一般来说,在编译或解释时,循环会转化为递归函数。当任务能够被相似的子任 务定义时,采用递归处理十分有效。例如,排序、搜索和遍历等问题往往有简洁的递归 解决方案。
3.递归函数的格式
递归函数在执行一个任务时,需要调用函数自身来完成一些子任务。在某些时候, 函数不需要继续调用函数自身就可以完成当前子任务。函数不再递归的情况称作基本情 形(base case,也称为基本情况)。而函数调用自身来执行子任务的情况就称作递归情形。可以用如下的形式描述所有的递归函数。
4.递归与迭代
•当到达基本情形时,递归终止。
*每次递归调用都需要额外的空间用于栈帧(内存)开销。
•如果出现无穷递归,程序可能会耗尽内存,并出现栈溢出。
*某些问题采用递归方法更容易解决。
迭代
•当循环条件为假时,迭代终止。
*每次迭代不需要任何额外的空间开销。
•由于没有额外的空间开销,所以若出现死循环,则程序会一直循环执行。采用迭代求解问题可能没有递归解决方案那样显而易见。
通常,迭代解决方案比递归解决方案更加有效(因为后者有函数调用的开销)。一个迭代算法可以通过使用栈代替递归函数的方式来实现,但通常是得不偿失的,这意味着任何能用递归求解的问题也能用迭代来求解。对于某些问题,没有明显的迭代求解算法。
5.什么是回溯
回溯是一种采用分治策略进行穷举搜索的方法。
有时求解一个问题的最好算法是尝试所有的可能性。
这种方法通常很慢,但有标准工具能够辅助该过程。
工具:生成基本对象的算法,排列、组合、一般字符串 等等。
通过剪枝回溯可以加速的穷举搜索。
6.回溯算法的经典用例
二进制串:产生所有的二进制串。
生成k进制串。
背包问题。
广义字符串。
哈密顿回路。
图着色问题。
7.回溯与递归的区别。
递归:
为了描述问题的某一状态,必须用到该状态的上一状态,而描述上一状态,又必须用到上一状态的上一状态……这种用自已来定义自己的方法,称为递归定义。形式如 f(n) = n*f(n-1), if n=0,f(n)=1。递归是一种算法结构,递归会出现在子程序中自己调用自己或间接地自己调用自己。最直接的递归应用就是计算连续数的阶乘,计算规律:n!=(n-1)!*n。
回溯:
从问题的某一种可能出发, 搜索从这种情况出发所能达到的所有可能, 当这一条路走到” 尽头 “的时候, 再倒回出发点, 从另一个可能出发, 继续搜索. 这种不断” 回溯 “寻找解的方法, 称作” 回溯法 “。回溯是一种算法思想,可以用递归实现。通俗点讲回溯就是一种试探,类似于穷举,但回溯有“剪枝”功能。