算法设计与分析——分治法求最大值和最小值

Description

给定n个数,在最坏情况下用 3n/2-2 次比较找出这n个数中元素的最大值和最小值。

要求只编写函数 

void maxmin(int a[],int low,int high,int *max,int *min).

系统会自动在程序的最后加上如下代码:

int main()
{
    int max,min,k,a[200];
    int m;
    while(scanf("%d",&k)&&k)
    {
        for(m=0;m<k;m++)
            scanf("%d",&a[m]);
        maxmin(a,0,k-1,&max,&min);
        printf("%d %d\n",max,min);
   
    }
} 

Input

包含多组测试数据。每组测试数据的第一个元素是整数的个数n,接下来是n个整数。0表示结束。 n<=200

Output

这n个数中的最大值和最小值。

Sample Input

5 1 8 2 4 3
3 2 4 1
0

Sample Output

8 1
4 1


如果之前遍历一遍需要比较n-1次,才能得到数组中的最大值和最小值,这显然是不符合预期要求的,这里应该采用的是分治思想。
分治法主要有三个步骤:
1.分解:将原问题划分为规模较小的几个子问题。
2.求解:子问题小到可以求解了,就去求解。
3.合并:将子问题的解合并为原问题的解。

 


 


对于本问题就是不断地进行二分,直到分解为不可分的一个数组元素,这个数组元素是最小子问题的最大值也是最小值,之后再逐一合并为原问题的解。
#include<cstdio>
#include<algorithm>
#define inf 0x3f3f3f3f
using namespace std;

void maxmin(int *a,int left,int right,int *max,int *min)
{
    int mid;
    int lmax=0,lmin=inf,rmax=0,rmin=inf;
    if(left==right)
    {
        *max=a[left];
        *min=a[right];
        return ;
    }
    mid=(left+right)/2;
    maxmin(a,left,mid,&lmax,&lmin);
    maxmin(a,mid+1,right,&rmax,&rmin);
    if(lmax>rmax)
    {
        *max=lmax;
    }
    else
    {
        *max=rmax;
    }
    if(lmin<rmin)
    {
        *min=lmin;
    }
    else
    {
        *min=rmin;
    }
    return ;
}
int main()
{
    int max,min,k,a[200];
    int m;
    while(scanf("%d",&k)&&k)
    {
        for(m=0; m<k; m++)
            scanf("%d",&a[m]);
        maxmin(a,0,k-1,&max,&min);
        printf("%d %d\n",max,min);
    }

}

使用分治法解决了本问题,但是3n/2-2 次比较是怎么计算得到的呢?
我们来分析一下本算法:
void maxmin(int *a,int left,int right,int *max,int *min)
{
    int mid;
    int lmax=0,lmin=inf,rmax=0,rmin=inf;
    if(left==right)
    {
        *max=a[left];
        *min=a[right];
        return ;
    }// ------------------------------------------------>O(1)
    mid=(left+right)/2;//------------------------------->O(1)
    maxmin(a,left,mid,&lmax,&lmin);//------------------->T(n/2)
    maxmin(a,mid+1,right,&rmax,&rmin);//---------------->T(n/2)
    if(lmax>rmax)
    {
        *max=lmax;
    }
    else
    {
        *max=rmax;
    }
    if(lmin<rmin)
    {
        *min=lmin;
    }
    else
    {
        *min=rmin;
    }
    return ;//------------------------------------------>O(1)
}

可以得到算法的递推表达式,进而求解。

 

posted @ 2019-09-04 17:10  王陸  阅读(13162)  评论(4编辑  收藏  举报