惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Google DeepMind News
Google DeepMind News
爱范儿
爱范儿
J
Java Code Geeks
L
LangChain Blog
V
V2EX
大猫的无限游戏
大猫的无限游戏
S
SegmentFault 最新的问题
博客园 - Franky
Microsoft Azure Blog
Microsoft Azure Blog
Jina AI
Jina AI
Blog — PlanetScale
Blog — PlanetScale
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
The Cloudflare Blog
博客园 - 司徒正美
B
Blog
G
Google Developers Blog
Stack Overflow Blog
Stack Overflow Blog
罗磊的独立博客
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Apple Machine Learning Research
Apple Machine Learning Research
Engineering at Meta
Engineering at Meta
MyScale Blog
MyScale Blog
有赞技术团队
有赞技术团队
Hugging Face - Blog
Hugging Face - Blog

博客园 - ~大器晚成~

我的2012 一个非重点校计算机专业毕业生的求职之路 Vim设置 推荐系统的循序进阶读物(从入门到精通) Hadoop 常见错误汇总 (转载) 信息检索技术——向量空间模型 信息检索技术——布尔检索 排序算法——堆排序 Hadoop 实现多个数据表的join操作 排序算法——快速排序 排序算法——冒泡排序 排序算法——选择排序 牛×的可视化排序 shell常用技巧 排序算法——插入排序 机器学习相关——文本分类综述 大公司 or 小公司 使用gdb进行调试高级篇 使用gdb进行调试中级篇
查找算法——找到序列中第二大的数(修正版)
~大器晚成~ · 2012-03-06 · via 博客园 - ~大器晚成~

今天来说一个简单的需求:在一个序列中找到第二大的元素。

一眼看到这个问题,感觉解决的方法有很多,因为这并不是一个困难的问题。随便一想,能有下面几种解法:

1 首先排序,然后取第二个位置的元素

2 循环遍历元素序列,找到最大的元素,然后将其移除。再重复此过程,得到第二大的元素

当然还有其他的思路,这里就不一一列举了。如果大家有什么好的想法,可以给我留言,咱们一起探讨。

仔细分析一下,不难发现,上面的方法虽然可以达到目的,但是效率都不高。第一种方法相当于一次排序过程,最快也要O(nlogn)的时间才能完成。而第二种方法需要循环遍历序列两次,O(n)+O(n)的时间复杂度虽然不是无法接受,但毕竟还是要循环两次。对于我们写软件的人来说,显然希望代码是“完美”的。因此在这里,提出一个只循环一次的方法,供大家借鉴参考。如果大家有好方法,欢迎提出。

废话不说,下面介绍算法思路:

我们既然可以循环遍历一次得到最大的元素,为什么不能保存住第二大的元素呢?当然可以,我们在比较元素大小时,只要把小的保存起来,经过一遍循环,这个元素就是第二大的元素了

代码就更简单了

int find_second_biggest(vector<int> &v){
int len = v.size();
int max,second;
if (len < 2){
return -1;
}
if (v[0]>v[1]){
second = v[1];
max = v[0];
}
else{
second = v[0];
max = v[1];
}
for (int i=2; i< len; i++){
if(max < v[i]){
second = max;
max = v[i];
}
else if (second < v[i]){
second = v[i];
}
}
return second;
}

相信看过代码,大家更清楚了吧,是不是很简单,而且只用了一次循环。这个问题很简单,写这个的目的就是要提醒自己,遇到问题要先多想一想,而不是一味的使用简单暴力的方法,多想半个小时有时会省上一天甚至更多的时间。

当然这个方法不一定是最好的,希望大家多多拍砖。

后记:之前提交了一个有错误的版本,可以说是给自己一个教训,还没有进行测试就放了上去,以至于犯了一个很基本的错误。看来以后还是要多试一下,不能太盲目自信了。这个版本是经过测试的,应该是个可用版本。如果大家发现有什么数据会导致错误,欢迎再指出。