王道书第二章应用题12【2013统考真题】

文章描述了一个寻找整数序列主元素的算法,该算法通过两次遍历数组,首先找到可能的主元素,然后验证其是否满足超过序列一半的数量。算法使用C++编写,具有O(n)的时间复杂度和O(1)的空间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

已知一个整数序列A = (a0,a1,...,an-1),其中0<=ai<n(0<=i<n).若存在ap1 = ap2 = ...=apm = x且m>n/2(0<=pk<n,1<=k<=m),则称x为A的主元素。(就是数组中存在大于n/2个元素都等于x).例如:A = (0,5,5,3,5,7,5,5),则5为主元素;又如A = (0,5,5,3,5,1,5,7),则A中没有主元素。假设A中的n个元素保存在一个一维数组中,请设计出一个尽可能高效的算法,找出A的主元素。若存在主元素,则输出该元素;否则输出-1.要求:

(1)给出算法的基本设计思想。

(2)根据设计思想,采用C或C++或java语言描述算法,关键之处给出注释

(3)说明你所设计的算法的时间复杂度和空间复杂度

(1)算法的主要设计思想:算法的策略是从前往后扫描数组元素,标记出一个可能成为主元素的元素Num。然后重新计数,确认Num是否是主元素。

算法分为两步:

1.选取候选的主元素。依次扫描所给数组中的每一个整数,将第一个遇到的整数Num保存到c中,记录Num出现的次数为1;若遇到的下一个整数仍等于Num,则计数加1,否则计数减1;当计数减到0时,将遇到的下一个整数保存到c中,计数重新记为1,开始新一轮计数,即从当前位置开始重复上述过程,直到扫描完全部数组元素(因为主元素的个数肯定大于数组元素个数的一半,若是Num加1,若不是Num则减1,若是主元素,那么Num肯定不会是0,就算主元在前面一部分,然后Num减到0,换成其他元素,因为其他元素个数肯定要小于数组元素一半,那么其迟早减到0,后面部分肯定是主元素,那么主元素的Num肯定不为0)

2.判断c中元素是否是正真的主元素。再次扫描该数组,统计c中元素出现的次数,若大于n/2,则为主元素;否则,序列不存在主元素。例如该例子:A = (0,5,5,3,5,1,5,7),Num = 1,也是大于0,所以需要验证

int Majority(int *A,int n)
{
  int i,c,count = 1;//c是用来存放记录数组A中的某一元素,若是主元素就输出c,这样就不需要再找
  c = A[0];//首先把数组A的第一个元素赋给c,设置A[0]为主元素,一步步向后扫描
  for(i = 1; i < n; ++i)//查找候选主元素
  {
    if(c == A[i])
		count++;//对A中的候选主元素计数,若是相等则加1
	else
	{
	  if(count > 0)//规定要count为0的时候换元素,若count大于0肯定要继续扫描
		  count--;
	  else
      {
	     c = A[i];//若是count=0,那么就将此时不和候选主元素相同的元素作为候选主元素
		 count = 1;//因为此时有一个元素,故count = 1

	}
  }
}
  if(count > 0)//来验证候选主元素是否为真正的主元素
  {
    for(i=count=0; i<n; ++i)//首先规定count和i为0,从头开始统计数组中和候选主元素相等元素的个数
	{
	  if(A[i] == c)
		  count++;
	}
  }
  if(count>n/2)
	  return c;//如果大于n/2,那么就是主元素
  else
	  return -1;//不存在主元素

}

(3)时间复杂度为O(n)(总共扫描元素为2n次,所以时间复杂度为O(n)),没有使用除该空间的其他额外空间,所以空间复杂度为O(1) 

完整代码

//假设整数序列为10个数
#include<stdio.h>
//函数说明
int Majority(int *A,int n);
int main(void)
{
  int A[10] = {1,3,0,1,1,8,1,1,1,9};
  int x = Majority(A,10);
  if(-1 == x)
	  printf("没有主元素\n");
  else
	  printf("主元素为:%d\n",x);
  return 0;
}

int Majority(int *A,int n)
{
  int i,c,count = 1;
  c = A[0];
  for(i = 1; i < n; ++i)
  {
    if(c == A[i])
		count++;
	else
	{
	  if(count > 0)
		  count--;
	  else
      {
	     c = A[i];
		 count = 1;

	}
  }
}
  if(count > 0)
  {
    for(i=count=0; i<n; ++i)
	{
	  if(A[i] == c)
		  count++;
	}
  }
  if(count>n/2)
	  return c;
  else
	  return -1;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值