您的位置:首页 > Web前端

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

2013-11-23 04:06 274 查看
剑指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。


// 652983    zhuli19901106    1370    Accepted    点击此处查看所有case的执行结果    3272KB    619B    80MS
// 201311180033
#include <cstdio>
#include <map>
using namespace std;

int main()
{
int tmp, ans;
int c;
int i, n;
map<int, int> mm; // must count the number of appearances of every element

while(scanf("%d", &n) == 1){
mm.clear();
scanf("%d", &ans);
mm[ans] = 1;
c = 1;
for(i = 1; i < n; ++i){
scanf("%d", &tmp);
++mm[tmp];
if(tmp == ans){
++c;
}else{
if(c > 0){
--c;
}else{
ans = tmp;
c = 1;
}
}
}

if(mm[ans] > n / 2){
printf("%d\n", ans);
}else{
printf("-1\n");
}
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: