算法設計與分析——分治法求最大值和最小值


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

可以得到算法的遞推表達式,進而求解。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM