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


    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
    ",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
    ",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)
    }
    
    

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

  • 相关阅读:
    Call指令和Ret指令讲解02 零基础入门学习汇编语言49
    指针01 零基础入门学习C语言41
    Call指令和Ret指令讲解03 零基础入门学习汇编语言50
    Call指令和Ret指令讲解01 零基础入门学习汇编语言48
    指针01 零基础入门学习C语言41
    指针02 零基础入门学习C语言42
    Call指令和Ret指令讲解02 零基础入门学习汇编语言49
    VC++2012编程演练数据结构《31》狄杰斯特拉算法
    VC++2012编程演练数据结构《30》弗洛伊德算法
    在Windows Azure Web Site上为Node.js自动安装NPM包
  • 原文地址:https://www.cnblogs.com/wkfvawl/p/11460280.html
Copyright © 2020-2023  润新知