zoukankan      html  css  js  c++  java
  • 找出数列中个数大于总数一半的元素(编程之美2.3)

    案例

    数列3, 2, 3, 1, 3, 3, 2, 3中,3就是个数大于总数大于一半的元素。

    思路一

    对数列排序,再扫描一边,找出元素个数超过一半的元素。此时需要排序,同时需要记录每个元素出现个数,费时、费空间。

    思路二

        对于排好序的数列,假设总数为N,那么N/2位置的那个数必定为所求之数,这就不需要记录每个元素的个数。

    思路三

         对于数列,不用排序。对于其中的任意两个不同的元素,去除之后,原来那个个数大于总数一半的元素个数仍然是大于剩下元素的一半的。利用该特性遍历一遍数列就可以找出这个总数大于一半的那个元素。

        具体的实施,不用每次去这些数中去找不同的两个数,只需记录当前候选目标值can,与此对应的为其个数num,目前访问的元素为cur

    • num==0: can=cur, num=1
    • num!=0 && can = cur: num++
    • num!=0 && can != cur: num--

    如果现在访问的元素与目标值相同,那么num++,不同num--;如果num=0,那么把候选元素改为此元素,并且赋值num=1

    图示

    通过简单分析可以得知

    • 当总素为偶数时,Num最终至少为2
    • 当总数为奇数时,Num最终至少为1

    参考代码

    #include<iostream>
    using namespace std;
    
    int Find(int a[], int N)
    {
        int count = 0;
        int candidate = 0;
        for(int i = 0; i < N; ++i)
        {
            if(count == 0)
            {
                candidate = a[i];
                count = 1;
            }
            else if(candidate == a[i])
                    ++count;
            else
                    --count;
            }
        return candidate;
    }
    
    int main()
    {
        int a[] = {3, 2, 3, 1, 3, 3, 2, 3};
        int val = Find(a, sizeof(a) / sizeof(int));
        cout << "Result:" << val << endl;
    }

    结果

    Result:3

    性能

    时间复杂度O(n), 空间复杂度O(1)

    扩展

    3个人发帖超过n/4,找粗这三个人

    void Find(Type* ID, int N, Type candidate[3])
    {
        Type ID_NULL;//定义一个不存在的ID
        int nTimes[3], i;
        nTimes[0]=nTimes[1]=nTimes[2]=0;
        candidate[0]=candidate[1]=candidate[2]=ID_NULL;
        for(i = 0; i < N; i++)
        {
            if(ID[i]==candidate[0])
            {
                 nTimes[0]++;
            }
            else if(ID[i]==candidate[1])
            {
                 nTimes[1]++;
            }
            else if(ID[i]==candidate[2])
            {
                 nTimes[2]++;
            }
            else if(nTimes[0]==0)
            {
                 nTimes[0]=1;
                 candidate[0]=ID[i];
            }
            else if(nTimes[1]==0)
            {
                 nTimes[1]=1;
                 candidate[1]=ID[i];
            }
            else if(nTimes[2]==0)
            {
                 nTimes[2]=1;
                 candidate[2]=ID[i];
            }
            else
            {
                 nTimes[0]--;
                 nTimes[1]--;
                 nTimes[2]--;
             }
        }
        return;
    }
  • 相关阅读:
    Oracle Core 学习笔记二 Transactions 和 Consistency 说明
    Oracle AUTO_SPACE_ADVISOR_JOB 说明
    Windows 下 ftp 上传文件 脚本
    Oracle 11g 中 Direct path reads 特性 说明
    Linux 使用 wget 下载 Oracle 软件说明
    Oracle 10g read by other session 等待 说明
    Oracle 11g RAC INS06006 Passwordless SSH connectivity not set up between the following node(s) 解决方法
    SecureCRT 工具 上传下载数据 与 ASCII、Xmodem、Ymodem 、Zmodem 说明
    Oracle RAC root.sh 报错 Timed out waiting for the CRS stack to start 解决方法
    Oracle RESETLOGS 和 NORESETLOGS 区别说明
  • 原文地址:https://www.cnblogs.com/kaituorensheng/p/3563877.html
Copyright © 2011-2022 走看看