面试题 <数组中出现超过一半的数字>(7)

# 面试题: 数组中出现超过一半 的数字


/*

题目: 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。 例如输入一个长度为9 的数组{1,2,

3,2,2,2,5,4,2}。 由于数字2 在这个数组中出现了 5次,超过了数组长度的一般,因此输出 5。

*/

# 题目分析:    看到这道题,相信大多数人和我一样想到的是,将数组中每一个元素出现的次数保存在一个数组里

面, 然后找出出现次数超过一半的元素; 那么这样是不是过于复杂,时间复杂度为 O(nlogn). 这样是最直观的算

法,但往往不是面试官想要的答案!

       如果我们仔细分析这道题不难发现,如果考虑这个数组的特性,那么这道题就会简单了许多! 找出数组中出现次

数超过一半的元素,如果我们将数组进行排序,那么,排序之后位于数组中间的元素一定是那个出现次数超过一半的

数字;  这个算法里面有快速排序的影子,因为我们为你调用了 是先快速排序时的 Partition 函数;
 
   
       当我们排序好数组之后;返回的Partition函数 选中数字的下标大于 n/2 那么中位数应该在他左边, 如果小于 n/2

那么中位数应该在它的右边, 如果等于n/2 那么它就是中位数。

# 代码实现:

bool g_bInputInvalib = false;

int Partition(int data[], int length, int start, int end)
{
	int index;
	int Small;

	if(data == NULL || length <= 0 || start < 0 || end >= length)
		return ;
	index = RandomInRange(start, end);
	//RandomInRange 是随机产生start和end中间的一个数;

	Swap(&data[index], &data[end]);
	//Swap 是交换两个数的函数;

	Small = start -1;
	for(index = start; index < end; ++index)
	{
		if(data[index] < data[end])
		{
			++Small;
			if(Small != index)
				Swap(&data[index], &data[Small]);
		}
	}
	++Small;
	Swap(&data[Small], &data[end]);

	return Small;
}

/*
CheckInvalibdaArry 函数判断输入的数组是不是无效的;
*/
bool CheckInvalibdaArry(int *number, int length)
{
	g_bInputInvalib = false;
	if(number == NULL || length <= 0)
		g_bInputInvalib = true
		
		return g_bInputInvalib;
}

/*
CheckMoreThanHalf 函数用来判断找出的出现频率最高的数是不是出现次数超过了数组长度的一半;
*/
bool CheckMoreThanHalf(int *numbers, int length, int number)
{
	int i = 0;
	int times = 0;
	bool isMoreThanHalf = true;

	for(i = 0; i <= length; ++i)
	{
		if(numbers[i] == number)
			times++;
	}
	bool isMoreThanHalf = true;
	if(times *2 <= length)
	{
		g_bInputInvalib = true;
		isMoreThanHalf = false;
	}
	return isMoreThanHalf;
}

int MoreThanHalfNum(int * numbers, int length)
{
	int result = 0;
	int middle = length >> 1;
	int start = 0;
	int end = length - 1;
	int index = Partition(numbers,length,start,end);

	if(CheckInvalibdaArry(numbers,length))
		return 0;

	while(index != middle)
	{
		if(index > middle)
		{
			end = index - 1;
			index = Partition(numbers, length, start, end);
		}
		else
		{
			start = index - 1;
			index = Partition(numbers, length, start, end);
		}
	}	
	
	     result = numbers[middle];
		if(!CheckMoreThanHalf(numbers, length,result))
			result = 0;

		return result;
}

over!

           
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值