Chinaunix首页 | 论坛 | 博客
  • 博客访问: 126976
  • 博文数量: 124
  • 博客积分: 3940
  • 博客等级: 中校
  • 技术积分: 1235
  • 用 户 组: 普通用户
  • 注册时间: 2009-05-05 18:57
文章分类

全部博文(124)

文章存档

2011年(52)

2010年(62)

2009年(10)

最近访客

分类:

2010-07-28 19:42:03

这是编程之美上的一道题目,大意是说:给n个数,其中有一个数出现的次数超过了一半,如何求出这个数。
 
这个题目一般的做法是先进行排序,然后统计数字出现的次数。这样的复杂度是O(nlogn)(貌似我刚开始也只能想出这样的算法...).然后书上提出一个稍微改进的方法,就是说排序后中间的那个数必然是出现次数超过一半的数(这不需要证明吧)。不过即使是这样,复杂度仍然是O(nlogn).
 
完美的解法是:如果每次删掉两个不同的数,那么在剩下的数中,那个数出现的次数仍然超过一半,这样重复下去,最后就可以求出这个数。这样总的复杂度就是O(n),并且只需要常数的内存(这是优于hash法的地方)。在实现的时候需要注意并不需要实际的去删除数。代码如下:
 

#include<iostream>
using namespace std;
int find(int *id,int N)
{
     int candidate;
     int nTimes,i;
     for(i=nTimes=0;i<N;i++)
     {
       if(nTimes==0)
       candidate=id[i],nTimes=1;
       else
       {
          if(candidate==id[i])
          nTimes++;
          else
          nTimes--;
     }
      }
      return candidate;
}
int main()
{
     int n;
     cin>>n;
     int num[100];
     for(int i=0;i<n;i++)
     cin>>num[i];
     int value=find(num,n);
     cout<<value<<endl;
     for(;;);
     return 0;
}


阅读(330) | 评论(0) | 转发(0) |
0

上一篇:VOA(2010-07-28)

下一篇:VOA(2010-07-29)

给主人留下些什么吧!~~