找出数列中个数大于总数一半的元素(编程之美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;
}
复制代码

 





本文转自jihite博客园博客,原文链接:http://www.cnblogs.com/kaituorensheng/p/3563877.html,如需转载请自行联系原作者

相关文章
|
存储 算法 C++
【C/C++ Vector容量调整】理解C++ Vector:Reserve与Resize的区别与应用
【C/C++ Vector容量调整】理解C++ Vector:Reserve与Resize的区别与应用
1137 1
|
编解码 Unix Linux
【Linux C/C++ 延时(延迟)函数比较】介绍Linux系统中常用的延时函数sleep、usleep、nanosleep、select和std::sleep_for()的区别和使用场景
【Linux C/C++ 延时(延迟)函数比较】介绍Linux系统中常用的延时函数sleep、usleep、nanosleep、select和std::sleep_for()的区别和使用场景
4097 1
|
算法 测试技术 C#
【单调栈】【网格】【柱图面积】85. 最大矩形
【单调栈】【网格】【柱图面积】85. 最大矩形
|
机器学习/深度学习 并行计算 Ubuntu
【Jetson Xavier NX 开发板深度学习环境配置流程】
【Jetson Xavier NX 开发板深度学习环境配置流程】
1669 0
【Jetson Xavier NX 开发板深度学习环境配置流程】
|
人工智能 移动开发
矩形分割
题目链接:http://noi.openjudge.cn/ch0111/03/ 一个二分的题目,估计是数据类型选择不当,折腾了好多天。所以,以后记得尽管使用long  long类型数据呵呵   描述 平面上有一个大矩形,其左下角坐标(0,0),右上角坐标(R,R)。
1188 0
|
算法
数理逻辑之 horn公式
Horn公式,中文名一般翻译成“霍恩公式”,也是范式的一种。 Horn原子有三: P::= ┴ | T |p Horn原子  分别是底公式、顶公式和命题原子。   Horn原子合取后的蕴含称为Horn字句: A::= P | PΛA C::= A → P ...
2729 0
|
C++ iOS开发 编译器
C++ Virtual详解
Virtual是C++ OO机制中很重要的一个关键字。只要是学过C++的人都知道在类Base中加了Virtual关键字的函数就是虚拟函数(例如函数print),于是在Base的派生类Derived中就可以通过重写虚拟函数来实现对基类虚拟函数的覆盖。
838 0
|
6天前
|
人工智能 运维 安全
|
3天前
|
人工智能 异构计算
敬请锁定《C位面对面》,洞察通用计算如何在AI时代持续赋能企业创新,助力业务发展!
敬请锁定《C位面对面》,洞察通用计算如何在AI时代持续赋能企业创新,助力业务发展!
|
5天前
|
机器学习/深度学习 人工智能 自然语言处理
B站开源IndexTTS2,用极致表现力颠覆听觉体验
在语音合成技术不断演进的背景下,早期版本的IndexTTS虽然在多场景应用中展现出良好的表现,但在情感表达的细腻度与时长控制的精准性方面仍存在提升空间。为了解决这些问题,并进一步推动零样本语音合成在实际场景中的落地能力,B站语音团队对模型架构与训练策略进行了深度优化,推出了全新一代语音合成模型——IndexTTS2 。
499 14