同时寻找最大数和最小数的最优算法 第二大数
???? 從一個(gè)容量為n的數(shù)據(jù)集合中同時(shí)找到最大數(shù)和最小數(shù)的最優(yōu)方法是:首先讓所有的元素參與兩兩比較,這樣總共比較了n/2次,最大數(shù)肯定在勝者組中,最小數(shù)肯定在敗者組中;然后從容量為n/2的勝者組中找到最大的數(shù),最少要比較n/2 - 1次;同理,從容量為n/2的敗者組中找到最小的數(shù),最少要比較n/2 - 1次。所以總共需要比較 (3n/2) - 2次。以上假設(shè)n為偶數(shù)。奇數(shù)同理。
這是同時(shí)尋找最大數(shù)和最小數(shù)的最優(yōu)算法。
?
??? 那么,我們要從一個(gè)容量為n的數(shù)據(jù)集(假設(shè)該數(shù)據(jù)集是一個(gè)集合,即沒有相同的元素)中找到第二大元素需要多少次比較呢?
??? 一種習(xí)慣的方法是:先找出最大的元素,這需要比較n-1次;然后從剩下的n-1個(gè)元素中找到最大的,這個(gè)元素就是我們要找的第二大元素,這需要比較n-2次。做一總共比較2n-3次。
但是,
??? 還有一個(gè)更優(yōu)的方法:
(1) 我們考慮淘汰賽的比較法,淘汰賽結(jié)束后,找出冠軍我們需要n-1次比較;如下圖所示,找到12需要比較7次。
(2) 此時(shí)我們要考慮到,亞軍應(yīng)該存在于敗給冠軍的這些選手中(否則,每個(gè)元素都至少有兩個(gè)元素比它大),由于與冠軍比過的元素個(gè)數(shù)為┌l(fā)og2n┐,從這些元素中找到最大值需要比較┌l(fā)og2n┐ - 1次;如下圖所示,亞軍應(yīng)該在10,11,4這三個(gè)元素中。否則,如果亞軍是5,那么冠軍12比它大,與它比較過的10也比它大,至少兩個(gè)元素大于5,所以5肯定不是亞軍的候選者。
?
(3)從而找出亞軍要比較n-1+┌l(fā)og2n┐-1 = n-2+┌l(fā)og2n┐次比較。這個(gè)算法是尋找亞軍的最優(yōu)算法。
分治與遞歸——最大值和次大值的最優(yōu)算法
問題描述:輸入n個(gè)數(shù),最壞情況下用?n + logn - 2?次比較找出當(dāng)中的最大值和次大值。
算法思想:根據(jù)題意出現(xiàn)logn,則肯定用到二分或者堆的思路,但是輸入的數(shù)沒有經(jīng)過排序,而且題目要求的計(jì)算量也不允許排序。這樣,就肯定會(huì)用到類似堆的思路,但是直接構(gòu)造堆等同于排序。堆的思想跟競(jìng)標(biāo)賽類似,都是父節(jié)點(diǎn)>=(<=)子節(jié)點(diǎn)。如果父節(jié)點(diǎn)都是從子節(jié)點(diǎn)而來,這樣就是競(jìng)標(biāo)賽;如果不是,這樣就是堆。既然不能排序又不能構(gòu)造堆,那就只能用競(jìng)標(biāo)賽的思想,通過二分來進(jìn)行最多logn次競(jìng)賽,選出最大值(冠軍),而次大值(亞軍)只能在與最大值的比較中被淘汰(亞軍的實(shí)力只可能輸給冠軍),故在所有被最大值(冠軍)淘汰的數(shù)值中選取次大值,最多也是logn次比較,滿足題意(由于題意只限制了比較次數(shù),故實(shí)現(xiàn)過程并沒有考慮時(shí)間復(fù)雜度和空間復(fù)雜度)
代碼實(shí)現(xiàn):
//最大值和次大值的最優(yōu)算法,數(shù)組中可能存在重復(fù)元素,不能處理最大值是0的情況
#include <stdio.h>
#define N 1000
int m[2*N];
int num[2*N];
int biaoji[N];
int bigger(int i)
{
????if(num[i]>num[i+1])
????{
????????biaoji[m[i+1]]=num[i];
????????return i;
????}
????else
????{
????????biaoji[m[i]]=num[i+1];
????????return i+1;
????}
}
int work(int a,int b)
{
????int i,j;
????while(a<b)
????{
????????for(i=a;i<b;i+=2)
????????{
????????????j=bigger(i);
????????????num[i/2]=num[j];
????????????m[i/2]=m[j];
????????}
????????if(i==b)
????????{
????????????num[i/2]=num[i];
????????????m[i/2]=m[i];
????????}
????????a=a/2;
????????b=b/2;
????}
????return num[a];
}
int work2(int l,int max)
{
????int i,flag=1;
????int bmax;
????for(i=l;i<2*l;++i)
????{
????????if(biaoji[i-l]==max)
????????{
????????????if(flag)
????????????{
????????????????flag=0;
????????????????bmax=num[i];
????????????}
????????????else if(bmax<num[i])
????????????????bmax=num[i];
????????}
????}
????return bmax;
}
int main()
{
????int i,l;
????int max,bmax;
????int f,start;
????while(true)
????{
????????printf("please putin the length:\n");
????????scanf("%d",&l);
????????if(l==0)
????????????break;
????????printf("please putin num[]:\n");
????????for(i=l;i<2*l;++i)
????????????scanf("%d",&num[i]);
????????for(i=l;i<2*l;++i)
????????????m[i]=(i-l);
????????max=work(l,2*l-1);
????????bmax=work2(l,max);
????????printf("the max is %d and the bmax is %d\n",max,bmax);
????}
?
????return 0;
}
總結(jié)
以上是生活随笔為你收集整理的同时寻找最大数和最小数的最优算法 第二大数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【付出总有回报】广州广汕公路科目三路考通
- 下一篇: 会车