数组中出现次数超过一半的数字
来自剑指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)时间内完成,要优于先排序然后找数组元素的方法。