zoukankan      html  css  js  c++  java
  • 算法设计与分析——分治法求最大值和最小值

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

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

  • 相关阅读:
    ubuntu 14.04 安装python包psycopg2
    vmare 往 virtualbox迁移
    docker-compose & docker 镜像/加速
    nodejs & npm & gulp 安装和配置
    airflow 优化
    airflow 部署
    windows 上vmare超卡的问题解决方案
    HDU 6781 Solo (贪心 + 优先队列)
    HDU 6779 Drink (最小费用流)
    HDU 6778 Car (状压DP)
  • 原文地址:https://www.cnblogs.com/wkfvawl/p/11460280.html
Copyright © 2011-2022 走看看