前言:
任何循环都能写成递归的形式
有一些语言没有循环,所以只能使用递归
循环改递归:
发现逻辑的“相似性”
不要忘记递归的出口(可利用参数改变)
方法的递归:
方法直接或者间接调用自身
寻找相似性:
理解案例:
我做了个梦,梦中我又做了一个梦,梦中我醒了,那么我是在梦中醒了,我需要再醒一次我才真的在现实中醒了。
山,庙。。。 山,庙 。。。。山,庙 。。。。山,庙。。。。
虽然故事内容是一样的(自身调用自身),但是这里的山和庙都是不同的,就算在一个庙中的和尚被烧死了,和当前讲故事的和尚都是没有关系的。
注意:
每一次调用自身的环境都是不一样的,所以他当前环境会先入栈,在栈中保存下来,
然后等出口条件后,进行出栈(先进后出),执行递归之外的代码。
递归案例:
斐波那契数列:
n球取出m个。不放回,求有多少种取法:
假设有一个特殊球x,那么就能把所有取法,分成两部分,就是认为划分,包不包含x。如果包含x就是 f(n-1,m-1)+ f(n-1,m),后者就是不包含
就说明,你一定会要取出幸运球,所以就是在n-1,中取出m-1个球,
还一种就是,不取出幸运球,所以就是在n-1,里面取出m个球
退出条件:
if(n<m){ reutrn 0} //取出的球比剩余的球还多,不可能取出,所以就是返回0
if(n == m){ return 1} //剩余的球刚好等于取出的球,那么就是返回1
if(m==0){return 1} //如果5个球中,一个都不取,那么就是一种方式
实现:
求n个元素的全排列:
思路:
求n个元素的全排列 abc acb bac bca cab cba
注意:就是每个元素都能占据开始的位置
所以我们从第k个元素开始,依次往后面给他交换位置。
实现:
求两个串的最大公共子序列的长度(递归)
子串:就是连续的,没有间隔的
子序列:就是不连续的,可以间隔的
abcdef --> abc abd bdf
方法一:使用递归
思路:
先取出两个串的第一个字符,x和y
如果x和y相等,对剩下的两个串的长度再加1就行了
如果两个不相等,把x去掉,剩下的那部分和y串进行比较,
或者把y去掉,剩下的和x串进行比较。
代码实现:
也可以考虑去掉尾元素,然后去匹配。
递归的参数是需要改变的,还有把原来的规模降低
注意:子序列可以比子串更多
求的是长度,不是具体的数值,所以更加简单
其实递归算法的效率并不是很高,所以我们可解,优化
求最长公共子序列(动态规划)
方法二:我们使用二维数组,矩阵,进行动态规划解出来,
代码实现:
总结:这里就是利用了两个矩阵,然后矩阵path就是纪录那些子问题的矩阵,然后通过递归,遍历出矩阵中值为0的下标,然后我们通过i-1下标,输出字符串1中的子序列。