主元素问题

主元素问题是一道非常经典的著名的问题,乍一看很简单,也很容易写出来,但越往后越难。

问题描述:给定一个长度为n的序列,若当中有数出现的次数>50%,输出这个数;否则输出NO。

 

还是先上数据:

7

3 3 1 1 3 2 3

输出是:

3

 

有什么好的方法吗?

建议你花时间先想一想

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

好啦,开始讲解。

Algorithm1:

将数组进行排序,堆排序或者快速排序,然后找出n/2+1那个位置的数。然后再扫一遍,统计这个数出现的次数。若该次数>n/2,那么这个数就是结果,否则输出NO。

原理:如果有数出现的次数>n/2,那么排序后,它一定会出现在n/2+1的位置上(想一想为什么)。

时间复杂度:O(N log N)

空间复杂度:O(N)

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int n,a[1005],i,cnt; 
int main()
{
    scanf("%d",&n);
    for(i=1;i<=n;i++)
        scanf("%d",&a[i]);
    sort(a+1,a+n+1);
    for(i=1;i<=n;i++)
        if(a[i]==a[n/2+1]) cnt++;
    if(cnt>n/2) printf("%d",a[n/2+1]);
        else printf("NO");
    return 0;
}
Algorithm1

 

Algorithm2:

用类似桶排序的方法,开一个数组储存每个数出现的次数。然后再扫一遍,找出那个出现次数最多的数,看看是否>n/2。

这种算法比较好理解。

时间复杂度:O(N+M)

空间复杂度:O(M)

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int n,a,x[100005],i,m=-9,cnt=-9,ans;
int main()
{
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        scanf("%d",&a);
        x[a]++;
        if(m<x[a]) m=x[a];
    }
    for(i=1;i<=m;i++)
        if(x[i]>ans) 
        {
            cnt=x[i];
            ans=i;
        }
    if(cnt>n/2) printf("%d",ans);
    else printf("NO");
    return 0;
}
Algorithm2

 

Algorithm3:

O(N)的算法来啦!

绝妙的思想:这样的算法有一个性质:如果在原数组中删除两个不同的数,那么在原数组中出现次数超过50%的数,在新数组中的次数也一定会超过50%。

仔细想一想为什么吧!一旦掌握了这种方法,那么此题就简单了。强烈建议读者自己用这种方法完成此题。

时间复杂度:O(N)

空间复杂度:O(N)

代码也给你们吧:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int n,a[1005],x,y,i;
int main()
{
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        if(y==0)
        {
            x=a[i];
            y++;
        }
        else
        {
            if(x==a[i]) y++;
            else y--;
        }
    }
    y=0;
    for(i=1;i<=n;i++)
        if(a[i]==x)
            y++;
    if(y>n/2) printf("%d",x);
    else printf("NO");
    return 0;
}
Algorithm3


再强调一遍:强烈建议读者完成此题,并想明白所有细节。

~祝大家编程顺利~

posted @ 2017-09-28 17:49  白驹过隙----青春绿  Views(906)  Comments(0Edit  收藏  举报