剑指Offer - 九度1370 - 数组中出现次数超过一半的数字
2013-11-23 03:55
- 题目描述:
-
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。
- 输入:
-
每个测试案例包括2行:
第一行输入一个整数n(1<=n<=100000),表示数组中元素的个数。
第二行输入n个整数,表示数组中的每个元素,这n个整数的范围是[1,1000000000]。
- 输出:
-
对应每个测试案例,输出出现的次数超过数组长度的一半的数,如果没有输出-1。
- 样例输入:
-
9 1 2 3 2 2 2 5 4 2
- 样例输出:
-
2
题意分析:
一个数组中可能有一个数字出现次数超过一半,如果确实有的话,参考《编程之美》上的经典做法。为每个值设置一个“可信度”,当同一个数字连续重复出现时,可信度加1;遇到不同的数时,可信度减1;可信度减到0了就丢弃这个数,换成当前比较的元素。最后剩下的元素就是出现次数超过一半的那个。扫描时间复杂度O(n),空间复杂度O(1)。
如果没有一个元素出现超过一半,则上面的结果变得不可预测,跟数据顺序、各数据个数有关,因此必须统计每个元素出现的次数,我用了map。时间复杂度O(n * log(n)),空间复杂度O(n)。最终得到的结果元素如果出现次数大于则是有效结果,输出之。否则表示没有元素超过一半,输出-1。
1 // 652983 zhuli19901106 1370 Accepted 点击此处查看所有case的执行结果 3272KB 619B 80MS 2 // 201311180033 3 #include <cstdio> 4 #include <map> 5 using namespace std; 6 7 int main() 8 { 9 int tmp, ans; 10 int c; 11 int i, n; 12 map<int, int> mm; // must count the number of appearances of every element 13 14 while(scanf("%d", &n) == 1){ 15 mm.clear(); 16 scanf("%d", &ans); 17 mm[ans] = 1; 18 c = 1; 19 for(i = 1; i < n; ++i){ 20 scanf("%d", &tmp); 21 ++mm[tmp]; 22 if(tmp == ans){ 23 ++c; 24 }else{ 25 if(c > 0){ 26 --c; 27 }else{ 28 ans = tmp; 29 c = 1; 30 } 31 } 32 } 33 34 if(mm[ans] > n / 2){ 35 printf("%d\n", ans); 36 }else{ 37 printf("-1\n"); 38 } 39 } 40 41 return 0; 42 }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步