2022.7.4寻找数组主元素—2013考研真题

【问题描述】这是一道2013年考研真题,已知一个整数序列A长度为N,其中若存在a,且a的个数大于N/2,则称a为A的主元素
例如:3 5 5 3 5 7 5 5,其主元素为5
又如:3 5 5 3 5 1 5 7,其中没有主元素。
假设元素保存在一个一维数组中,请设计一个尽可能高效的算法,找出主元素。若存在主元素则输出该元素否则输出
【输入形式】一个整数数组,以0作为结束输入
【输出形式】主元素,若没有则输出-1
【样例输入】3 5 5 3 5 7 5 5 0
【样例输出】5
【样例说明】长度为8,共有5个‘5’

1.对于主要元素(主元素)的一些理解
主要元素(主元素)是在一整数序列(长度是N)中出现次数大于N/2的元素,因为整数序列本身长度就是N,那么只要该整数序列中存在主元素,主要元素就是唯一的

思路:

思路一:穷举

找出元素中每一个数在数组中出现的次数。时间复杂度是O(N^2)

思路二:排序

先对数组进行排序,然后重头开始遍历一遍计算每个数字出现的次数。这种方法的时间复杂度取决于对数组采取何种排序方法;其中使用快排进行排序的时间复杂度是O(N*logN+N)

思路三

另外再开一个数组b,数组b的下标对应着数组a中出现各个数字,数组b的值就是数组a中各个数字出现的次数。这种方法时间复杂度为O(N),就是数组中的元素是负数的时候,这种方法似乎就不适用了,因为数组的下标是要大于等于0的。不知道是不是自己知识有限,没有想到解决的办法

思路四

只要一个数组存在主元素,那么主元素就是唯一的,并且主元素的个数大于N/2(数组的长度是N)。因而可以将数组中的主元素与其他元素一一抵消,也就是一个主元素抵消一个其他元素,最后还会剩下1个或者多个主元素。

但是对于一个输入的数组,我们并不知道数组是否有主元素、以及主元素是谁;因此我们只需要先假设目前的元素是主元素,并设置一个计数器Count=1(为什么初始值是1,是因为目前元素自己本身就算是出现了一次),其中Count是用来记录候补主元素将所有其他元素(除了候补主元素的其他元素)抵消完之后,候补主元素出现的次数。

(1)当Count>0的时候就意味着我们假设的候补主元素就是我们要求的主元素
例如:数组a={3,3,3,3,1,5,2}此时通过眼观,很明显的可以看出数组a是有主元素的,并且主元素是3。进行理论的分析的话,就是先假设a[0]是数组a的主元素,并设置一个计数器Count=1,然后就是写一个循环,将a[1]-a[6]逐个与a[0]进行对比,如果相同的话,就将Count++(也就是a[0]这个元素出现的次数又多了1);如果不相同的话,就让Count–(也就是让一个a[0]与一个其他元素相抵消掉),最后的时候Count是等于1的,所以a[0]=3也就是我们要求的主元素

(2)当Count=0的时候也就意味着我们假设的候补元素并不是我们要求的主元素
例如:数组a={3,4,4,5,7,4,4},刚开始的时候我们是假设主元素是a[0]=3,Count=1;之后进行判断就发现了a[1]!=a[0],所以Count–,即Count=0,也就是3并不是我们抵消后最后的主元素,也可以理解成3不是我们要求的主元素(但是这种说法会有一些欠缺,下面便会发现,所以这种说法仅仅适用于自己更好的理解这种情形)。这个时候就已经可以判断a[0]不是我们要求的主元素了,所以我们要对Count和候补主元素进行更新修改;即假设候补主元素是a[2],令Count=1。之后便发现a[3]!=a[2],Count–,即Count=0,这也就意味着4不是我们抵消后最后的主元素;此时便不可以再理解成4不是我们要求的主元素,因为通过眼观法,可以看出来数组a的主元素就是4嘛。

(3)Count<0这种情况并不会出现,因为在Count=0的时候,就对候补主元素和Count进行了更新了
最后的最后,输出的时候若Count!=0时,需要重新遍历一遍判断这个数字是否为真正的主元素;例如数组a={5,5,6,7,8}的时候,实际上是没有主元素的,但是不检验的话就会输出8,这就是错误的结果。

总的来说的话:

请添加图片描述

代码如下:

#include <iostream>
#define Maxsize 1000
using namespace std;

int a[Maxsize],len;

void Input()
{
    int i=0;
    while(1)
    {
        cin>>a[i];
        if(a[i]==0) break;
        i++;
    }
    len=i;
}

void Majority()
{
    int cur=a[0],Count=1;
    for(int i=1;i<len;i++)
    {
        if(a[i]==cur) Count++;
        else
        {
            if(Count!=0) Count--;
            else
            {
                cur=a[i];
                Count=1;
            }
        }
    }
    if(Count!=0)
    {
    	int sum=0;
    	for(int i=0;i<len;i++)
    	if(a[i]==cur)
    	sum++;
    	if(sum>len/2) cout<<cur;
    	else cout<<"-1";
    }
    else
        cout<<"-1";
}
int main()
{
    Input();
    Majority();
    return 0;
}
  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值