zoukankan      html  css  js  c++  java
  • 有趣的问题系列-主元素问题

    什么是主元素问题?

    给定一个有(n)个元素的数列,保证其中有一个数出现的次数严格大于(50\%),求这个数。

    怎么做?

    朴素桶计数

    我们第一想到的,至少我第一想到的就是桶计数。出现一个数,把它扔进桶中。桶计数是很基本的概念,如果你这都不懂,赶紧百度去!
    代码实现也很简单,纯手敲吧,有锅不修。

    #include <iostream>
    #include <cstdio>
    
    int bucket[10086];
    
    int main() {
        int n;
        std :: cin >> n;
        for(int i = 1; i <= n; i++) {
            int x;
            std :: cin >> x;
            bucket[x]++;
        }
        for(int i = 1; i <= 10086; i++)
            if(bucket[i] > n / 2) {
                cout << i << std :: endl;
                break;
            }
        return 0;
    }
    

    但是桶计数的局限性非常大,非常容易爆空间,int的范围就可以让这玩意儿直接gg。

    如果你想到了离散化,说明你还是很聪明的,蟹蟹为你点赞。但是离散化并不是最好的方法,照样有很多东西会卡离散化。我们直接pass掉桶计数吧。

    好吧我知道有些人又开始叫map了……稍安勿躁,我有更好的方案。

    排序

    这叫做更好的方案????蟹蟹你真是绝了。
    先别急着爆踩我,首先一个数列如果存在主元素,则排序后第(dfrac{n}{2})个位置上的数一定是主元素。
    我们就有了新方法:

    #include <iostream>
    #include <cstdio>
    
    const int maxn = 10005;
    int a[maxn];
    
    int main() {
        int n;
        for(int i = 1; i <= n; i++)
            std :: cin >> a[i];
        
        sort(a + 1, a + n + 1);
        std :: cout << a[n / 2 + 1];
        return 0;
    }
    

    很明显此算法的复杂度是(O(nlog n)),但还有没有直接(O(n))的做法呢?
    还真有。以前还是个初学者的时候看到主元素问题思路就停止在这里了,前天有机会重新见到了这道题,我又有了新的想法。

    互相抵消法

    我们把序列中所有不相同的两个数互相抵消,剩下的就是主元素。因为主元素在数列中出现的数量严格大于(50\%),所以这个做法的正确性不难保证。这个方法非常的微妙。
    这里可以用很多种实现方式,我选择用stack食用= =

    #include <iostream>
    #include <cstdio>
    
    const int maxn = 10000005;
    int s[maxn];
    int top;
    
    int main() {
        int n;
        scanf("%d",&n);
        while(n--) {
            int x;
            scanf("%d",&x);
            s[top++] = x;
            if(top == 1) continue;
            if(s[top - 1] != s[top - 2]) top -= 2;
        }
        printf("%d
    ",s[top - 1]);
        return 0;
    }
    

    后记

    这个问题真的很有趣,也验证了我思维的成长过程。两年前我只能想到(O(nlog n))的做法,如今我却能已经独立思考出(O(n))的做法。所以我在进步,我也会一直进步的。感触真的是颇深。

  • 相关阅读:
    【Mysql学习笔记】浅析mysql的binlog
    HBase 学习笔记---守护进程及内存调优
    字符集例子-同一字符不同字符集编码不同及导入导出的乱码
    随机访问
    格式化的代价
    读写文本文件
    缓冲
    加速I/O的基本规则
    序列化再探讨
    数据库I/O:CMP、Hibernate
  • 原文地址:https://www.cnblogs.com/crab-in-the-northeast/p/major-element-question.html
Copyright © 2011-2022 走看看