DSA_07:递归算法
2020-03-30 08:02:01来源:博客园 阅读 ()
DSA_07:递归算法
前面讲解了复杂度分析、数组、链表、栈、队列,今天讲解递归算法。
递归,可以说同前面这些基础数据结构一般用途广泛,在诸多算法中,这是非常基础,常用的。
简单举几个例子:
1. 二叉树前序、中序、后续遍历可用递归。
2. 深度优先算法可以递归,如迷宫寻路、迷宫生成等。
3. 快排、归并排序可用递归。
4. 二分查找可用递归。
5. 解决实际问题时可用递归。
同样,递归的用途也是多不胜数。想要正确、灵活去应用该算法,需要掌握其一些特性。
本文通过一个基础的例子学习该算法,并给出该算法的各种特性技巧。
例:这里有 N 阶台阶,你一次可以跨越 1阶、2阶 或 3阶,那么,你有多少种不同的走法走完这 N 阶台阶呢?
如果你曾遇到过该题,你会觉得非常简单。但是如果你不会递归,你会觉得非常困难,用人脑几乎不可能想清楚,后面会给出解释。
这里直接给出方法:
走完这 N 阶有多少种走法?然后你一次可以跨越 1~3 阶,令走完这 N 阶有 F(N) 种方法。
则走到 N 阶的路径是否等于:走到 N-1 阶的方法 + 走到 N-2 阶的方法 + 走到 N-3 阶的方法?
当然是的,这里或许需要花费时间细细品味一下。
你可以理解:走到 N 阶 可以从 N-1 阶上去,也可从 N-2 阶上去,还可以从 N-3 阶上去,这样说是否理解了呢?
因此有 F(n) = F(n-1) + F(n-2) + F(n-3)。
终止条件呢:F(1) = 1,F(2) = 2,F(3) = 4。相信这能够想清楚。
因此有下面代码:
int Fn(int n) { if (n == 1) return 1; if (n == 2) return 2; if (n == 3) return 4; if (n <= 0) return -1; return Fn(n - 1) + Fn(n - 2) + Fn(n - 3); }
现在,让我们看看该算法的分解图:
你是否发现问题了呢?
F(4) 被重复计算了!!!
随着 N 的增加,被重复计算的会越来越多,性能开销太大!!!
回过头看,为何人脑无法处理过来呢?你可以看出,其复杂是 O(3^n),仅次于阶乘复杂度,你的大脑能承受这样的指数爆炸吗?
递归会占用栈内存,对空间的开销非常大,小心爆栈。
递归算法如何优化呢?一方面是将递归用迭代法写,另外可用尾递归优化,这里不再细说。
在力扣等地方刷题时有时间限制,它会给出大量的测试数据,我们有什么办法使得运行时间非常小呢?
就本题而言,如果告诉你,台阶最多 30 阶,请看代码:
class Solution { public: Solution() { gen(); } int Fn(int n) { if (n <= 0 || n > 30) return -1; return val[n - 1]; } private: int val[30]; void gen() { val[0] = 1; val[1] = 2; val[2] = 4; for (int i = 3; i < 30; ++i) val[i] = val[i - 1] + val[i - 2] + val[i - 3]; } };
这样一来,原本需要递归才能解决的问题,直接变成查表法了,时间空间复杂度一下子均变为 O(1)。
我们看看 30 阶台阶时有多少种走法呢?
Fn(30) = 53798080
超过 5千万,这更加验证了人是无法完成这样庞大的计算的。
爬楼梯:力扣第 70 题。
利用查表法,让我们看看战绩:
现在总结递归算法及一些需要注意的地方:
1. 递归需要满足的三个条件:
a. 一个问题的解可以分解为几个子问题的解。
b. 这个问题与分解之后的子问题,除了数据规模不同,求解思路完全一样。
c. 存在递归终止条件。
2. 如何编写递归代码:
a. 找到如何将大问题分解为小问题的规律。
b. 基于此写出递推公式。
c. 再推敲终止条件。
d. 最后将递推公式和终止条件翻译成代码。
3. 递归代码要警惕堆栈溢出
4. 怎么将递归代码改写为非递归代码 或 如何优化递归代码
5. 递归有利有弊:
利是递归代码的表达力很强,写起来非常简洁。
弊就是空间复杂度高、有堆栈溢出的风险、存在重复计算、过多的函数调用会耗时较多等问题。
关于递归算法到此暂时结束,关于其优化以及将递归转化为非递归本文并未深入讲解,这在以后会多次讲解到。
原文链接:https://www.cnblogs.com/teternity/p/DSA_07.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- C++ rand函数 2020-06-10
- OpenCV开发笔记(五十九):红胖子8分钟带你深入了解分水岭 2020-05-24
- 类欧几里得算法 2020-05-16
- 算法笔记刷题6 ( PAT 1003我要通过 ) 2020-05-08
- 无法正确通过算法题目都是哪些原因造成的? 2020-04-05
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash