递归 | 分治

<目录

这两个算法有部分重合,所以一起讲。

递归 \(\sf\small\color{gray}Recursion\)

递归是递归函数的灵活运用。
说到底,它是一个 \(\color{blue}\texttt{C++}\) 的一个语言特性。
在函数内部调用函数,会使得思路更加清晰明了。

观察生活,很多事情随着规模或阶段的上升而变得越来越复杂。
然而,此规模或阶段往往又和前面的规模或阶段有着联系。
找出这个联系并解决问题的算法就叫递推。

这是我在 递推 | 差分与前缀和 里写过的一句话。
找出了关系,使用数组迭代,是递归。找出了关系,用递归函数迭代,就是递归。
递归的板子不是死的。它很活,视具体递推(归)式而变。

递归函数

int f(int a)
{
return f(a);
}

这严格来说不算一个递归函数。它永远调用自己,造成 \(\sf\color{red}死递归\)

int f(int a)
{
return f(a-1);
}

这样呢?
的确不是重复调用自己,可是 a 可以无限小下去,依然是死递归。
怎么办呢?

int f(int a)
{
if(a==1) return 1;
return a+f(a-1);
}

这样呢?
只要 a 是大于一的,那么这个函数就不会死。

递归函数三要素

\(\boxed{\sf调用自身}\boxed{\sf状态转移}\boxed{\sf递归边界}\)
此三者缺一不可,不然函数将失去意义。

运用递归函数

这里举一些例子,方便理解。

阶乘

使用递归函数求 \(\sf n!\) 的值。
此题用循环将非常简单。可是用递归函数呢?
调用自身是当然的。
我们按照递推的思想,把定义拆开:

\[\begin{aligned} \sf n!&\sf =n\times(n-1)\times(n-2)\times...\times 3\times 2\times 1 \\ \sf &\sf =n\times(n-1)! \end{aligned} \]

边界呢?
自然是 \(1!=1\) 啦!
至此,思路已经非常清晰了。上代码!

int factorial(int a)
{
if(a==1) return 1;
return a*factorial(a-1);
}

斐波那契数

1 1 2 3 5 8 ...

我们在 递推 | 差分与前缀和 已经推过它的递推式了:

\[\sf F(i)= \begin{cases} \sf F(i-1)+F(i-2)&\sf(i>2)\\ \sf 1&\sf(i=1or2) \end{cases} \]

现在我们用递归实现。

int fibonacci(int a)
{
if(a==1) return 1;
if(a==2) return 2;
return fibonacci(a-1)*fibonacci(a-2);
}

至此,有一个小问题暴露了:
F(n) 已经调用过 F(n-1)F(n-2) 了,F(n-1) 又调用了 F(n-2) ,不就浪费资源了吗?
既然已经调用过,那我把它记住不就好了?

斐波那契数 - 记忆化搜索

每一次调用都看看有没有算过,如果算过,就直接拿出来用,没有就记住他。

int Ans[1000];
int fibonacci(int a)
{
if(Ans[a]!=0) return Ans[a];
if(a==1) return 1;
if(a==2) return 2;
Ans[a]=fibonacci(a-1)*fibonacci(a-2);
return Ans[a];
}

算法优劣

递归肯定是没有递推优的。每一次调用函数都会新开空间,进入与返回也会花时间,递归层数一多,栈空间还可能炸。
那为什么还用递归?
如果你不知道递推层数,你怎么知道你要什么时候停下来?
而递归 if 里的东西什么都可以。
况且递归思维难度小啊。

分治 \(\sf\small\color{gray}Partition\)

分治分治,分而治之。

字面意思,把一个问题分成两个,三个甚至多个问题。
其实分治可以想递推一样,用循环解决,二分就是一种这样的例子。
还有的,就用递归函数解决吧。

运用

快速模

int FastMod(int a,int b,int k)
{
if(b==1)return a%k;
const int o=FastMod(a,b/2,k)%k;
if(b%2) return (a%k*o%k*o%k)%k;
else return (o%k*o%k)%k;
}

此处使用了 % 的性质,不熟悉的同学可以去学学 % 的性质。

区别

我认为吧,分治和递归的本质区别是,一个是由小一点的规模迭代而来,一个是由一半的,三分之一甚至四分之一的相同子问题迭代而来。


完结散花qwq

posted @   PCwqyy  阅读(5)  评论(0编辑  收藏  举报  
Your new comment will be here
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示