【寻找主元素(四种方法)】

题目:已知一个整数序列 A=(a0, a1, …, a(n-1)),其中 0<=a(i)<n(0<=i<n)。若存在 a(p1)=a(p2)=…=a(pm)=x 且 m>n/2(0<=p(k)<n,1<=k<=m),则称 x 为 A 的主元素。例如,A=(0, 5, 5, 3, 5, 7, 5, 5),则 5 为主元素;又如,A=(0, 5, 5, 3, 5, 1, 5, 7),则 A 中没有主元素。假设 A 中的 n 个元素保存在一个一维数组中,请设计一个尽可能高效的算法,找出 A 的主元素。若存在主元素,则输出该元素;否则输出 -1。

代码如下:
方法一(做题时自己花费时间最短的方法):运用两层循环,每一次都遍历一遍数组,看计数是否大于n/2,满足就输出(时间复杂度为O(N*N))

int Majority(int A[],int n)
{
	for(i=0;i<n;i++)
	{
		count=0;
		for(j=0;j<n;j++)
		{
			if(i!=j&&A[i]==A[j])
				count++;
		}
		if(count>n/2)
			return A[i];
	}
	return -1;
}

方法二:运用快排思想,然后再查找中间的数即可 (直接查找中间的数是因为主元素的个数超过一半,所以如果存在主元素,在数组n/2处一定是主元素)(时间复杂度为 (快排的时间复杂度) O(nlogn))

给出快排代码:排好后在主函数中查询A[n/2]即可,此代码为快排核心代码
//快速排序分割函数
int Partition(SqList &L,int low,int high)
{	
	int pivotekey = L.data[low]; //保存枢轴
	while (low<high)
	{
		while (low < high&&L.data[high] >= pivotekey) --high;
		L.data[low] = L.data[high];
		while (low < high&&L.data[low] <= pivotekey) ++low;
		L.data[high] = L.data[low];
	}
	L.data[low] = pivotekey;
	PrintList(L);
	return low;
}
// 快速排序 升序
void QuickSort(SqList &L, int low, int high)
{
	if (low < high)
	{
		int pivotloc = Partition(L,low,high);
		QuickSort(L,low,pivotloc-1);
		QuickSort(L, pivotloc + 1, high);
	}
}

方法三(次优解):计数排序思想,用空间换时间,运用一个辅助数组,把出现的元素存到对应数组位置,然后遍历找出最大的,看是否满足个数大于n/2即可(时间复杂度O(n)空间复杂度O(n))

int Major(int A[],int n){
int k,*p,max;
p=(int *)malloc(sizeof(int)*n)
for(k=0,k<n,k++) p[k]=0; //将申请的动态数组清0
max=0;//max初始为0
for(k=0,k<n,k++)
{
	p[A[k]]++ //将数组A中位置为k的元素放到p数组的A[k]位置上
	if(p[A[K]]>P[max]) max=A[k];//记录次数最多的数,A[K]为p数组的位置,也是对应的个数最多的元素
}
if(p[max>n/2]return max;
else return -1;
}

方法四:(最优解但是是不容易想到的,没看到过一定想不到的。这种方法的原理是如果一个数组中存在一个主元素(个数大于n/2),如果两个不相等的元素两两抵消,那么最终一定剩下的是主元素。
简单的说就一个大小为n数组中存在一个元素的个数大于n/2,则如果用这个数组中其他元素和该主元素进行抵消的话,最后剩下的一定是主元素,因为主元素个数最多。
该方法可以在O(n)的时间内找到主元素。(时间复杂度O(n),空间复杂度O(1))

int Majority(int A[], int n){
	int i,c,count=1;
	c=A[0];
	for(i=1;i<n;i++//查找候选元素
		if(A[i]==c)
			count++;//对A中的候选元素进行计数
		else
			if(count>0)
				count--;
			else    //更换主元素,重新计数
			{
				c=A[i];
				count=1;
			}
	if(count>0for(i=count=0; i<n; i++)
			if(A[i]==c)
				count++;
	if(count>n/2) return c;
	else return -1;	
}

算法为自己学习使用,多理解思想,有错误之处还请多多包涵!!!

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

喜欢下雨t

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值