蒟蒻说算法——递归
想要表情包吗?我可以给你,请看下面。
emmmm…:
呵呵~
今天不发题解,让我们来谈谈算法。这此提到的算法是非常的常见,这一次的算法就是——递归。
递归的原理
想要了解递归,就必须要了解一下递归的工作原理,才能成功的使用。递归的本质就是递归函数调用自身。可以粗略的理解为无限制造for嵌套,是不是很简单 😃?然后我们要知道递归是把调用的递归函数全部丢到一个栈里面,再一个一个去处理。so easy~
递归函数的框架
框架并不难,跟函数很像,看一下下面的代码框架:
#include<bits/stdc++.h>
using namespace std;
void/*函数类型,就是int,bool,void之类的*/ fill/*函数名*/(/*需要的参数*/){
if(/*返回条件或超出界限*/){
return ;//如果是void不用return其他的,其他都要
}
/*其它乌七八糟的代码,中间一定要出现调用自身函数,不然就不是递归啦*/
}
int main(){
fill(/*乌七八糟的参数*/);
return 0;
}
其它的自己编码,就是开头的if绝对不能漏哦,漏了的话,呵呵呵~ 你可以试试,肯定会一直调用调用再调用,只要你不return的话。
使用递归的题目
使用递归的题目也是非常的多,来一道比较经典的题目:斐波那契数列,题目大家应该都知道,在这里就不细说题目了。
直接看一下代码:
#include<bits/stdc++.h>
using namespace std;
int f(int num){
if(num == 1||num == 2){//返回的地方
return 1;
}else{
return f(num-1)+f(num-2);//前两项之和
}
}
int main(){
int n;
cin>>n;
cout<<f(n);
}
挺精简的吧,简单的作者都没什么注释可写的了。只要你试试,40左右就爆炸了(超时)
你只要输出一下每次调用的是数列中的第几项,就会得到一下结果(n = 7)的时候是这样的:
显而易见,第五项被重复了两遍,第四项被重复了3遍,是不是很惊喜?如果数据大一点,再大一点的话,就会重复计算很多遍,导致大量时间浪费,所以超时不是事。所以优化就是必须的了。
递归优化
递归的优化作者知道一种,叫做记忆化搜索,用人话来说就是每次要计算时就先找一下在结果数组中有没有,有的话直接使用,没有的话先算出结果,存到结果数据里面,方便下一次调用。只不过有一个要注意的东西就是使用是要先尽量的减少参数,不然的话你就有可能使用三维数组甚至四维。再说了,参数那么多,也不容易命中,是吧。给大家看一下优化后的代码:
#include<bits/stdc++.h>
using namespace std;
int result[100];
int f(int num){
if(num == 1||num == 2){//返回的地方
return 1;
}else{
if(result[num]!=0){
return result[num];
}else{
cout<<"f("<<num<<")"<<endl;
result[num] = f(num-1)+f(num-2);
}
return result[num];//前两项之和
}
}
int main(){
int n;
cin>>n;
cout<<f(n);
}
运行结果是这样的:
是吧?这样就快很多了吧?用文件输入的话n = 40都只要0.5632s就OK了,上面那个作者中间10输错了,耗掉了时间,总体来说是快了很多了。
递归就讲完了,不会太难吧。