版权申明:本文为博主窗户(Colin Cai)原创,欢迎转帖。如要转贴,必须注明原文网址
http://www.cnblogs.com/Colin-Cai/p/12664044.html
作者:窗户
QQ/微信:6679072
E-mail:6679072@qq.com
所谓众数,源于这样的一个题目:一个长度为len的数组,其中有个数出现的次数大于len/2,如何找出这个数。
基于排序
排序是第一感觉,就是把这个数组排序一下,再遍历一遍得到结果。
C语言来写基本如下:
int find(int a, int len)
{
sort(a, len);
return traverse(a, len);
}
排序有时间复杂度为O(nlogn)的算法,比如快速排序、归并排序、堆排序,而遍历一遍排序后的数组得到结果是时间线性复杂度,也就是O(n)。所以整个算法时间复杂度是O(nlogn)。
寻找更好的算法
上面的算法实在太简单,很多时候我们第一感就可以出来的东西未必靠谱。
我们是不是可以找到一种线性时间级别的算法,也就是Θ(n)时间级别的算法?Θ是上下界一致的符号。其实我们很容易证明,不存在比线性时间级别低的算法,也就是时间o(n),小o不同于大O,是指低阶无穷大。证明大致如下:
如果一个算法可以以o(n)的时间复杂度解决上述问题。因为是比n更低阶的无穷大,那么一定存在一个长度为N的数组,在完成这个算法之后,数组内被检测的元素小于N/2。假设算法运算的结果为a,然后,我们把这个数组在运算该算法时没有检测的元素全部替换为成同一个不是算法所得结果a的数b。然后新的数组,再通过算法去运算,因为没有检测的数不会影响其算法结果,结果自然还是a,可实际上,数组超过N/2次出现的数是b。从而导致矛盾,所以针对该问题的o(n)时间算法不存在。
我们现在可以开始想点更加深入点的东西。
我们首先会发现,如果一个数组中有两个不同的数,将数组去掉这两个数&#