zoukankan      html  css  js  c++  java
  • 主元素问题

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

    问题描述:给定一个长度为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


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

    ~祝大家编程顺利~

  • 相关阅读:
    SpringBoot中Word转PDF
    使用Word模板导出标准表Word样式文件
    Chrome 80及以上版本 中 Iframe 跨域 Cookie 的 Samesite 问题
    Visual Studio 2022 Key
    《HelloGitHub》第 69 期
    重玩 40 年前的经典游戏小蜜蜂,这次通关了源码
    那些年的开源项目,你跑起来了吗?
    图片处理看这篇就完了「GitHub 热点速览 v.21.48」
    年底巩固下 CS 知识「GitHub 热点速览 v.21.49」
    误入 GitHub 游戏区,意外地收获颇丰
  • 原文地址:https://www.cnblogs.com/llllllpppppp/p/7607671.html
Copyright © 2011-2022 走看看