分治法求最大和最小值


例題:金塊問題

老板有一袋金塊(共n塊,n是2的冪(n>=2) ),最優秀的員工得到其中最重的一塊,最差的員工得到其中最輕的一塊。假設有一台比較重量的儀器,請你用最少的比較次數找出最重和最輕的金塊。

這個問題其實就是輸入n個數,找出最大和最小數的問題。

解決問題的策略

蠻力策略:對金塊逐個進行比較查找。(掃描數組一輪,尋找最大和最小的數。)該策略需要進行(n-1)次的比較才能得到Max和min。

分治法(二分法)策略:問題可以簡化為在n個數里面尋找最大和最小值。

(1)將數據等分為兩組(兩組數據的個數可能相差1),目的是分別選取其中的最大(小)值。

(2)遞歸分解直到每組元素的個數<=2,則可以簡單地找到其中的最大(小)值。

(3)回溯時合並子問題的解,在兩個子問題的解中大者取大,小者取小,即合並為當前問題的解。

 1 #include<stdio.h>
 2 #include<time.h>
 3 #include<stdlib.h>
 4 int maxMin(int *a,int i,int j,int *max,int *min);
 5 int main()
 6 {
 7     int *a;
 8     int i,n;
 9     int max,min;
10     
11     scanf("%d",&n);
12     a=(int *)malloc(sizeof(int)*n);
13     srand((unsigned int)time(0));
14     for(i=0;i<n;i++) a[i]=rand()%91+10;
15     for(i=0;i<n;i++)
16     {
17         printf("%d ",a[i]);
18         if((i+1)%5==0) printf("\n");
19     }
20     printf("\n\n");
21     maxMin(a,0,n-1,&max,&min);
22     printf("%d %d\n",max,min);/**/
23     return 0;
24 }
25 /*---------------------------------------------------
26 函數名稱:maxMin
27 函數功能:在數組a的區間[i,j]范圍內尋找一個最大值和一個最小值並通過指針*max和*min返回。
28 -----------------------------------------------------*/
29 int maxMin(int *a,int i,int j,int *max,int *min)
30 {
31     int mid;
32     int lmax,lmin,rmax,rmin;
33     if(j==i) { *max=a[i]; *min=a[i]; return 0;}
34     else if(j-i==1)
35     {
36         if(a[i]>a[j])  {*max=a[i];*min=a[j];return 0;}
37         else  {*max=a[j];*min=a[i];return 0;}
38     }
39     else
40     {
41         mid=i+(j-i)/2;
42         maxMin(a,i,mid,&lmax,&lmin);
43         maxMin(a,mid+1,j,&rmax,&rmin);
44         if(lmax>rmax)   *max=lmax;
45         else   *max=rmax;
46         if(lmin<rmin)     *min=lmin;
47         else   *min=rmin;
48     }
49     return 0;
50 }
二分策略代碼

 

由該問題演變出來的另一個問題:尋找數組當中最大的兩個數和最小的兩個數。下面的代碼實現了該算法,同樣采用的是二分策略。【該算法稍有欠缺:對假如最大數或最小數有相同的多個值,可能得到的最大(小)值與次大(小)值是一樣的。】

 1 #include<stdio.h>
 2 #include<time.h>
 3 #include<stdlib.h>
 4 int maxMin2(int *a,int i,int j,int *max1,int *max2,int *min1,int *min2);
 5 int max(int a,int b);
 6 int min(int a,int b);
 7 int  main()
 8 {
 9     int *a;
10     int i,n;
11     int max1,max2,min1,min2;
12     
13     scanf("%d",&n);
14     a=(int *)malloc(sizeof(int)*n);
15     srand((unsigned int)time(0));
16     for(i=0;i<n;i++) a[i]=rand()%91+10;
17     for(i=0;i<n;i++)
18     {
19         printf("%d ",a[i]);
20         if((i+1)%5==0) printf("\n");
21     }
22     printf("\n\n");
23     maxMin2(a,0,n-1,&max1,&max2,&min1,&min2);
24     printf("%d %d\n%d %d\n",max1,max2,min1,min2);/**/
25     return 0;
26 }
27 int maxMin2(int *a,int i,int j,int *max1,int *max2,int *min1,int *min2)
28 {
29     int mid,t;
30     int lmax1,lmax2,lmin1,lmin2,rmax1,rmax2,rmin1,rmin2;
31     if(j-i==2) 
32     {
33         *max1=max(a[j],max(a[i],a[i+1]));
34         *min1=min(a[j],min(a[i],a[i+1]));
35         t=a[i]+a[j]+a[i+1];
36         *max2=t-*max1-*min1;
37         *min2=*max2;
38         return 0;
39     }
40     else if(j-i==1)
41     {
42         if(a[i]>a[j]){*max1=a[i];*max2=a[j]; *min1=a[j];*min2=a[i];return 0;}
43         else{*max1=a[j];*max2=a[i]; *min1=a[i];*min2=a[j];return 0;}
44     }
45     else
46     {
47         mid=i+(j-i)/2;
48         maxMin2(a,i,mid,&lmax1,&lmax2,&lmin1,&lmin2);
49         maxMin2(a,mid+1,j,&rmax1,&rmax2,&rmin1,&rmin2);
50         if(lmax1>rmax1)
51         {
52             *max1=lmax1;
53             if(lmax2>rmax1) *max2=lmax2;
54             else *max2=rmax1;
55         }
56         else
57         {
58             *max1=rmax1;
59             if(lmax1>rmax2) *max2=lmax1;
60             else *max2=rmax2;
61         }
62         if(lmin1<rmin1)
63         {
64             *min1=lmin1;
65             if(lmin2<rmin1) *min2=lmin2;
66             else *min2=rmin1;
67         }
68         else
69         {
70             *min1=rmin1;
71             if(lmin1<rmin2) *min2=lmin1;
72             else *min2=rmin2;
73         }
74     }
75     return 0;
76 }
77 int max(int a,int b)
78 {    return a>b?a:b;       }
79 int min(int a,int b)
80 {    return a<b?a:b;       }
View Code

對於該算法的缺陷,暫時還不知道如何解決了呵呵

 



免責聲明!

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



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