有一些公司招聘时还在用这个题目,但是网上流传的代码有问题,所以有必要发一篇博文。解决这个问题的算法有很多种,最巧妙的算法思路我提一嘴。该算法充分利用了核心值特性(也就是出现次数超过一半的值),利用两个辅助变量coreNum,count。coreNum用于临时存储数组中的数据,count用于存储某个数出现的次数。开始时coreNum存储数组中的第一个数,count为0,如果数组出现的数于coreNum相等,则count加1,否则就减1。如果count为0,就把当前数组中的数赋给coreNum,count设为1。因为指定的数出现的次数大于数组长度的一半,所有count++与count--相抵消之后,最后count的值是大于1的,coreNum中存的那个数就是出现最多的那个数。小于1,则返回-1,表示没有找到coreNum。当等于1时,需要进行特殊检查。网上流传的代码有问题,对于形如{2,2,2,3,3,3,4}。这样的数据其实是无解的。但网上流传的代码会返回4。
发现该问题后,我做了一些简单粗暴的改进,也是当count为1时,再次线性扫描一遍来做最终的验证。
class Program
{
static int[] testArray = { 2,2,2,3,3,3,3,3,3,3,5,6,6 };
static int searchCoreNum(int[] nums)
{
if (nums == null || nums.Length == 0)
{
return -1;
}
int coreNum = 0, count = 0;
for (int i = 0; i < nums.Length; i++)
{
if (count == 0 )
{
coreNum = nums[i];
count = 1;
}
else
{
if (coreNum == nums[i])
count++;
else
count--;
}
}
if (count > 1)
return coreNum;
else if (count == 1)
{
int reCount = 0;
foreach (int num in nums)
if (num == coreNum) reCount++;
if (reCount > nums.Length / 2)
return coreNum;
else
return -1;
}
else
return -1;
}
static void Main(string[] args)
{
Console.WriteLine(searchCoreNum(testArray));
Console.ReadKey();
}
}