算法--找出数组中出现次数超过一半的数
作者:陈太汉
算法--找出数组中出现次数超过一半的数
每当我看到经典的算法题,就怀念高中,感觉很多算法题就是高中的题目,谁叫哥只读了个专科,高数基本相当没学。
有空要看看高数啊,想当年数学那是相当的......
#include <iostream>
using namespace std;
class FindTheOne
{
public:
方法一
第一个想到的方法是见一个二维数组,一维存数组中的数据,二维存这个数出现的次数。出现次数最多的那个数就是要找的那个数
由于某个数出现的次数超过数组长度的一半,所以二维数组的长度只需要这个数组的一半。代码实现如下,
当然这个方法很糟糕,时间复杂度和空间复杂度都比较大,想练手的我还是写了一下。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
{
if(NULL==A || len<=0)
{
return ;
}
int (*B)[2]=newint[len/2][2];
B[0][0]=A[0];
B[0][1]=1;
int t=0;
bool notExist=true;
for(int i=1;i<len;++i)
{
for(int j=0;j<t;++j)
{
if(A[i]==B[j][0])
{
B[j][1]++;
notExist=false;
break;
}
}
if(notExist)
{
B[t++][0]=A[i];
}
}
int max=1;
int k=0;
for(int i=0;i<len/2;++i)
{
if(B[i][1]>max)
{
max=B[i][1];
k=i;
}
}
theOne=B[k][0];
}
方法二
将数组排序,最中间的那个数就是您要找的数。
如果出现最多的那个数是最小的,那么1至(n+1)/2都是那个数
如果出现最多的那个数是最大的,那么(n-1)/2至n都是那个数
如果不是最小也不是最大,当这个数由最小慢慢变成最大的最大的数时,你会发现中间的那个数的值是不变的。
综上所述,中间的那个数就是你要找的那个数。
时间复杂度就是你排序用的时间。排序真的不想写了(可以参考《我的另一篇博客》)。大家都知道排序还是相当费时的,当然这个方法还是不太好。
方法三
这个方法借用了别人的思路。
在这里我做一下简单的分析。
这个算法的时间复杂度是O(n),另外用了两个辅助变量。
k用于临时存储数组中的数据,j用于存储某个数出现的次数。
开始时k存储数组中的第一个数,j为0,如果数组出现的数于k相等,则j加1,否则就减1,如果j为0,就把当前数组中的数赋给k
因为指定的数出现的次数大于数组长度的一半,所有j++与j--相抵消之后,最后j的值是大于等于1的,k中存的那个数就是出现最多的那个数。
下面这个算法只适合数组中数组中某个数的出现次数超过数组长度一半的数组,符合题意。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
{
if(NULL==A || len<=0)
{
return-1;
}
int k, j=0;
for(int i=0;i<len;++i)
{
if(j==0)
{
k=A[i];
}
if(k==A[i])
{
++j;//有人说++j比j++有先天的优势,不知你是否听说,如果你也听说,有没有想过More Effective C++(C++程序员必看书籍)
}else
{
--j;
}
}
return k;
}
};