題目:找出一個數(shù)組中的次最大元素。
方法一:
int getSecond(int* ptr,int n)
{
int max,second;
second=*ptr;
max=second;
for(int i=0;i<n;i++)
{
if(*(ptr+i)>max)
{
second=max;
max=*(ptr+i);
}
else if(*(ptr+i)<max)
{
if(max==second || second<*(ptr+i))
second=*(ptr+i);
}
}
if(max==second)
printf("no second number\n");
else
printf("the second number is %d\n",second);
return second;
}
該段代碼是用一次循環(huán)來找出最大值和次最大值。
核心思想描述如下:
可以把最大值和次最大值抽象為一個寶塔模型,比如簡單的我們用二樓來表示最大值,一樓
來表示次最小值。要注意二樓和一樓不僅僅是一個二樓比一樓高的問題,更重要的是它們緊
緊相鄰。
1。首先將max和second均置為數(shù)組中的第一個數(shù)
2。接受下一個數(shù),如果比max大,那么我們很自然會想到把整個數(shù)賦給max。但是此刻我們就
忘記了處理second,其實忽略這一步的主要原因在于我們沒有清醒的認識到“二樓和一樓緊
緊相鄰”這層關系,其實更新最大值的同時也就意味著原先的最大值變?yōu)榱水斍暗拇巫畲笾?/p>
,因此需要同時也更新second=max;然后此次處理結束,再取出下一個數(shù)。
3。如果比max小,那么需要再判斷這個數(shù)是否比second大,如果大的話,那么就更新second
的值為當前取出的這個數(shù)。但是這里需要考慮到剛開始初值將max和second賦予了相同的值,
因此要特別的再加一個判斷,如果max==second成立,則依然更新second的值,因此可以合寫
到一個if語句的判斷中去,然后用“||”連接。
最后,這個方法還有個特別的地方,就是對于取出的數(shù)等于max時該如何處理,經(jīng)過分析可以
得知,這種情況絕對不可以簡單的歸到第2步或第3步之中去,否則會出大問題。因此只能舍
棄這種情況,因此代碼中用的是else if而不是else。
============================================================
int getSecond(int* ptr,int n)
{
int max,second;
max=*ptr;
for(int i=0;i<n;i++)
if(*(ptr+i)>max)
max=*(ptr+i);
second=max;
for(i=0;i<n;i++)
if(*(ptr+i)!=max && *(ptr+i)>second || max==second)
second=*(ptr+i);
if(max==second)
printf("no second number\n");
else
printf("the second number is %d\n",second);
return second;
}
這是第二種方法,用兩次for循環(huán)的方法來實現(xiàn)同樣的結果,這就比較容易理解了,第一次
for循環(huán)找到max,第二次for循環(huán)從剔除了“等于max值”的那些元素的剩余數(shù)組元素中尋找
“最大值”,但是唯獨有個需要注意的地方就是對于第二次for循環(huán)時second的初值問題,我
們不可以給second賦一個我們自己指定的初值,因為如果second值在算法結束后依然不變的
話,我們并不知道second的最終結果是沒有被改過,還是被數(shù)組中一個值相同的元素更改過
,因此我們在算法的最后都要判斷max是否等于second,如果等于就是沒有次最大值,如果不
等于就返回second值。因此,在這里,我們必須把給second賦max初值,這就帶來一個問題,
因此在判斷是否更新second的時候,就要加上這種情況,也就是當max==second時,我們依然
需要更新second的值。
其實,還有最后一個問題,就是如果沒有second值時,我們是不是不應該返回這個數(shù)啊?如
果都是自然數(shù),我們可以返回-1以示錯誤,但是我們處理的數(shù)組是int型的,因此不能保證其
中沒有負值,因此就無法返回一個數(shù)值來表明不存在次最大值,所以我建議讓函數(shù)返回一個
bool值,然后在函數(shù)參數(shù)中用一個int指針來回傳second值,在調(diào)用該函數(shù)時,可以先判斷返
回值是否為true,再決定是否利用second值進行后續(xù)處理,這樣做也可以在getSecond函數(shù)傳
參非法時立即返回false,比如指針為null,或者長度n為負數(shù)。
最后,只有細心的讀者才能察覺,上面的代碼還不是最優(yōu)的,我們可以將這種方法中的判斷
改為:if(*(ptr+i)!=max && (*(ptr+i)>second || max==second))
測試代碼如下:
void main()
{
int a[]={7,7,7,7,7,6,7,6,7,7,7,7};
getSecond(a,12);
}