题目:找出一个数组中的次最大元素。
方法一:
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;
}
该段代码是用一次循环来找出最大值和次最大值。
核心思想描述如下:
可以把最大值和次最大值抽象为一个宝塔模型,比如简单的我们用二楼来表示最大值,一楼
来表示次最小值。要注意二楼和一楼不仅仅是一个二楼比一楼高的问题,更重要的是它们紧
紧相邻。
1。首先将max和second均置为数组中的第一个数
2。接受下一个数,如果比max大,那么我们很自然会想到把整个数赋给max。但是此刻我们就
忘记了处理second,其实忽略这一步的主要原因在于我们没有清醒的认识到“二楼和一楼紧
紧相邻”这层关系,其实更新最大值的同时也就意味着原先的最大值变为了当前的次最大值
,因此需要同时也更新second=max;然后此次处理结束,再取出下一个数。
3。如果比max小,那么需要再判断这个数是否比second大,如果大的话,那么就更新second
的值为当前取出的这个数。但是这里需要考虑到刚开始初值将max和second赋予了相同的值,
因此要特别的再加一个判断,如果max==second成立,则依然更新second的值,因此可以合写
到一个if语句的判断中去,然后用“||”连接。
最后,这个方法还有个特别的地方,就是对于取出的数等于max时该如何处理,经过分析可以
得知,这种情况绝对不可以简单的归到第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循环的方法来实现同样的结果,这就比较容易理解了,第一次
for循环找到max,第二次for循环从剔除了“等于max值”的那些元素的剩余数组元素中寻找
“最大值”,但是唯独有个需要注意的地方就是对于第二次for循环时second的初值问题,我
们不可以给second赋一个我们自己指定的初值,因为如果second值在算法结束后依然不变的
话,我们并不知道second的最终结果是没有被改过,还是被数组中一个值相同的元素更改过
,因此我们在算法的最后都要判断max是否等于second,如果等于就是没有次最大值,如果不
等于就返回second值。因此,在这里,我们必须把给second赋max初值,这就带来一个问题,
因此在判断是否更新second的时候,就要加上这种情况,也就是当max==second时,我们依然
需要更新second的值。
其实,还有最后一个问题,就是如果没有second值时,我们是不是不应该返回这个数啊?如
果都是自然数,我们可以返回-1以示错误,但是我们处理的数组是int型的,因此不能保证其
中没有负值,因此就无法返回一个数值来表明不存在次最大值,所以我建议让函数返回一个
bool值,然后在函数参数中用一个int指针来回传second值,在调用该函数时,可以先判断返
回值是否为true,再决定是否利用second值进行后续处理,这样做也可以在getSecond函数传
参非法时立即返回false,比如指针为null,或者长度n为负数。
最后,只有细心的读者才能察觉,上面的代码还不是最优的,我们可以将这种方法中的判断
改为: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);
}