图文详解递归:以二分法求数组中的最大值为例

什么是二分法

在查找有序数组中的某个元素的时候,我们往往就会首先想到二分法。比较目标数和数组的中间数的大小,然后将数组中的数据不断分为两份,从而判断目标数据应该处于数组的左半段还是右半段。这种二分法查找的时间复杂度为O(logN)。故而一般在有序数组中我们常会考虑二分法。

但是二分法并不是只能使用在有序数组中,求解某些特殊问题如求解一个数组上的局部极小值也可以使用二分法。还有我们今天想要讨论的求解数组中的极大值也可以使用二分法来进行求解。

图解二分法

二分法求最大值代码如下:

int process(int* a,int L,int R){
    //L是该段数据的左边界
    //R是该段数据的右边界
    if(L == R)
       return *(a+L);
    int mid = L+((R-L)/2);//计算中点
    int Leftmax =  process(a,L,mid);
    int Rightmax = process(a,mid+1,R);
    return (Leftmax>Rightmax)?Leftmax:Rightmax;
}

从代码上我们最直观能看出来的是,我们使用process求解出数组左半部分和右半部分的最大值,然后比较左右两部分得到的最大值的大小,返回该值,作为process求解该左半部分+右半部分中最大值的结果。这种函数自己调用自己进行求解的方法我们称之为递归。

让我们更加细致的分析这段代码。

递归停止条件是:L == R,即是该段数据的左右边界重合,也就是说分解这个数组直至其左右两部分为单个元素时。
假设该数组为{5,4,3,7,6,2,9,8,10},将其传入该函数process中,由于此时0=L!=R=9所以if中的条件不成立,计算这个数组的中点mid = 4,将左半部分数据送至process中求解该部分的最大值。进入到第二个process计算Leftmax = process(a,0,4),此时if条件还是不成立,继续二分,进入第三个process计算Leftmax = process(a,0,2)…直至进入第五个process计算Leftmax = process(a,0,0),if条件成立,return得到Leftmax = process(a,0,0)=a[0]=5。该过程如下:
在这里插入图片描述
得到Leftmax = process(a,0,0)的返回值后,开始计算Rightmax = process(a,1,1)此时这个process中的if条件也是成立的,可以计算得到Rightmax = process(a,1,1)=a[1]=4,然后返回max(Rightmax,Rightmax)作为process(a,0,1)的结果也就是process(a,0,2)中的Leftmax = process(a,0,1)=5,图解如下:
在这里插入图片描述
然后按照以上的方式继续进行直至求出 Leftmax = process(a,0,4)Rightmax = process(a,5,9)的值,返回其中的最大值就得到了process(a,0,9)的结果,也就是我们目标数组的最大值。

也就是说,我们也会发现只有当if条件成立时,此时才不会继续调用process,而是开始返回一个值作为前一层process中的结果,我们也称其为递归停止条件,在该程序中是:L == R,即是该段数据的左右边界重合,也就是说分解这个数组直至其左右两部分为单个元素时。我们宏观的看一下这个函数的调用过程就是以下:

下图为二分过程:
在这里插入图片描述

下图为求解最大值的过程,我们可以将方框看作是求解框内数max的process:
在这里插入图片描述

我们将上图与下图对照看(没有带框就是指其为上图对应框中的结果)也就是:
在这里插入图片描述
这就是我们二分求解数组最大值的递归过程。

二分法求解数组最大值代码

#include <stdio.h>

int process(int* a,int L,int R){
    if(L == R)
       return *(a+L);
    int mid = L+((R-L)/2);//计算中点
    int Leftmax =  process(a,L,mid);
    int Rightmax = process(a,mid+1,R);
    return (Leftmax>Rightmax)?Leftmax:Rightmax;
}

int main(){
    int n;
    printf("该数组长度为:");
    scanf("%d",&n);
    int a[n];
    printf("请输入一个组数:");
    for(int i=0;i<n;i++){
        scanf("%d",&a[i]);
    }


    int max = process(a,0,n-1);
    printf("%d \n",max);
}
  • 10
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值