这道题的题目为:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
解题思路分为三步:
(1)对数组进行排序,排序之后位于中间的那个数字就是出现的次数超过数组长度的一半的数。
(2)使用Partition算法对数组进行排序,使得排序后随机选取的数字的左边数都小于它,右边都大于它。如果选中的数字下标正好是n/2,那么这个数字就是数组的中位数。
(3)如果它的下标小于n/2,那么中位数位于它的右边,则可以在它右边的部分查找。反之则去它的左边部分查找。
代码如下:
#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>
//标记数组是否有效
bool numberuse = false;
void swap(int *a, int *b)
{
int t = *a;
*a = *b;
*b = t;
}
//Partition排序算法
int Partition(int array[], int left, int right)
{
int begin = left;
int end = right;
while (begin < end)
{
while (begin < end && array[begin] <= array[right])
{
begin++;
}
while (begin < end && array[right] <= array[end])
{
right--;
}
swap(array + begin, array + end);
}
swap(array + begin, array + right);
return begin;
}
//确保输入的数组有效
bool IsUse(int *number, int length)
{
numberuse = false;
if (number == NULL&&length <= 0)
numberuse = true;
return numberuse;
}
//确保result在数组中有出现次数超过一半
bool CheckMoreThanHalf(int * number, int length, int result)
{
int times = 0;
for (int i = 0; i < length; ++i)
{
if (number[i] == result)
times++;
}
//确保result有效
bool IsMoreThanHalf = true;
if (times * 2 <= length)
{
numberuse = true;
IsMoreThanHalf = true;
}
return IsMoreThanHalf;
}
int MoreThanHalf(int * number, int length)
{
if (IsUse(number, length))
return 0;
int start = 0;
int end = length - 1;
int middle = (end - start) / 2;
int index = Partition(number, start, end);
while (index != middle)
{
if (index > middle)
{
end = index - 1;
index = Partition(number, start, end);
}
else
{
start = index +1;
index = Partition(number, start, end);
}
}
int result = number[middle];
if (!CheckMoreThanHalf(number, length, result))
result;
return result;
}