剑指Offer - 九度1370 - 数组中出现次数超过一半的数字

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

 

你可能感兴趣的:(数组)