剑指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 }

 

 posted on 2013-11-23 04:06  zhuli19901106  阅读(281)  评论(0编辑  收藏  举报