找出数组中出现次数超过数组长度一半的元素

数组中出现次数超过一半的数字

来自剑指offer,其中两种方法思想都很好,感谢作者。

#include <iostream>
using namespace std;

/*
两种思想:第一种想到统计上的中位数定义如果存在满足条件的数,则肯定该数为数组的中位数,找到中位数
没必要对整个数组进行排序,只需要利用快速排序中的Partition方法找到某个元素应该在middle位置,
然后检查是否满足次数超过数组大小的一半。
*/

int Partition(int *A,int low,int high)
{
	int pivotkey=A[low];
	while (low<high)
	{
		while (low<high&&A[high]>=pivotkey)
		{
			high--;
		}
		A[low]=A[high];
		while (low<high&&A[low]<=pivotkey)
		{
			low++;
		}
		A[high]=A[low];
	}
	A[low]=pivotkey;
	return low;
}

bool confirmNum(int *array,int number,int len)
{
	int time=0,i;
	for (i=0;i<len;i++)
	{
		if (array[i]==number)
		{
			time++;
		}
	}
	if (time*2>len)
	{
		return true;
	}
	else
		return false;
}

void MoreThanHalfArray(int *array,int len)
{
	int middle=len/2;
	int index,start=0,end=len-1;
	index=Partition(array,start,end);
	while (index!=middle)
	{
		if (index>middle)
		{
			end=index-1;
			index=Partition(array,start,end);
		}
		else
		{
			start=index+1;
			index=Partition(array,start,end);
		}
	}
	int result=array[middle];
	if (confirmNum(array,result,len))
	{
		cout<<"exsit this element is "<<result<<endl;
	}
	else
		cout<<"not found this element\n";
}

/*
另外一种就是进行标号的遍历数组,因为某个元素超过一半,保存数组中的数字和其出现次数
如果下一个相同则次数加1,不同减1,如果次数变为0则保存数字为下一个数,最终情况是出现次数最多的元素
最终保存下来,然后检查是否超过半数
*/

void MoreThanHalf(int *array,int len)
{
	int i;
	int result,time=0;
	for (i=0;i<len;i++)
	{
		if (time==0)
		{
			result=array[i];
			time=1;
		}
		else if (array[i]==result)
		{
			time++;
		}
		else
			time--;
	}
	if (confirmNum(array,result,len))
	{
		cout<<"exsit this element is "<<result<<endl;
	}
	else
		cout<<"not found this element\n";
}

int main()
{
	int array[]={1,2,3,2,2,2,5,4,2};
	MoreThanHalfArray(array,9);
	MoreThanHalf(array,9);
	return 0;
}

这两种实现都能在O(n)时间内完成,要优于先排序然后找数组元素的方法。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值