递归,分治算法,动态规划,贪⼼算法的区别联系
递归:编程技巧,解决问题的思维⽅式
分治算法:解决更具体问题的算法思想,多数基于递归,分解的子问题不重复,如归并排序
动态规划:解决更具体问题的算法思想,多数基于递归,但最终大都又不是递归,重叠⼦问题性质(子问题重复)
贪⼼算法:动态规划的一个子集,高效解决更特殊问题
1.警惕堆栈溢出:可以声明一个全局变量来控制递归的深度,从而避免堆栈溢出。
2.警惕重复计算:通过某种数据结构来保存已经求解过的值,从而避免重复计算。
笼统的讲,所有的递归代码都可以改写为迭代循环的非递归写法。如何做?抽象出递推公式、初始值和边界条件,然后用迭代循环实现。
基本思想
某个函数直接或者间接地调⽤⾃⾝,这样就把原问题的求解转换为许多性质相同但是规模更⼩的⼦问题。我们只需要关注如何把原问题划分成符合条件的⼦问题,⽽不需要去研究这个⼦问题是如何被解决的。
性质相同子问题、关注划分子问题
递归和枚举的区别在于:枚举是横向地把问题划分,然后依次求解⼦问题,⽽递归是把问题逐级分解,是纵向的拆分。 #🤔
加深理解的问题
1. 如何给⼀堆数字排序? 答:分成两半,先排左半边再排右半边,最后合并就⾏了,⾄于怎么排左边和右边,请重新阅读这句话。
2. 孙悟空⾝上有多少根⽑? 答:⼀根⽑加剩下的⽑。
3. 你今年⼏岁? 答:去年的岁数加⼀岁,1999 年我出⽣。
代码特征
注意:明⽩⼀个函数的作⽤并相信它能完成这个任务,千万不要试图跳进细节!!!即相信该函数的结果是正确的,并高效去利用它
结束条件:最简子问题
自我调用:缩小规模,即划分子问题
数学归纳法和递归
一个是缩小规模,有结束条件
一个是扩大规模,无结束条件——无穷
选择原因
1、递推的思维是正常⼈的思维,总是看着眼前的问题思考对策,解决问题是将来时;递归的思维,逼迫我们倒着思考,看到问题的尽头,把解决问题的过程看做过去时
2、练习分析问题的结构,当问题可以被分解成相同结构的⼩问题时,你能敏锐发现这个特点,进⽽⾼效解决问题
3、跳出细节,从整体上看问题。不仅简洁漂亮而且可解释性强。非递归需要考虑边界计算细节易出bug且难调试
4、堆栈消耗额外空间
常见案例
遍历二叉树(前中后序)——>遍历多叉数