ZZ一道百度面试题:求数组中出现次数超过一半的数

来源:互联网 发布:儿童故事软件大全 编辑:程序博客网 时间:2024/05/24 06:56

一道百度面试题
 
现在有一个数组,已知一个数出现的次数超过了一半,请用O(n)的复杂度的算法找出这个数。
 
Yzf给出的算法:

1.    遍历数组,如果元素的个数是1,算法退出

2.    元素两两比较,如果两个数相同,则删去一个,如果两个数不同,则都删去。

3.    重复执行1

 
复杂度分析:
每次遍历至少要删掉n/2个元素,首次遍历元素的个数是n,

segma = n + n/2 + n/4 + …

         = O(2n)

 
Fxzy给出的算法:
遍历整个数组,同时记录当前的出现次数最多的数Dm和出现次数Cm,方法是这样的:

如果当前元素和记录的数不同,则把Cm减1,如果出现次数小于零,则用当前元素取代Dm, Cm = 1.

否则, Cm++

最后可以保证Dm即为所求。

 

算法正确性分析:

充分利用题目所给信息:一个数K出现次数超过一半,所以K一定唯一。使用相同留一个,不同全删掉的方法,只可以删掉了n/2个K,而因为K的个数>n/2,所以最后留下的一定是K. fxzy的算法复杂度更低,时间O(n),空间O(1),是这个问题的复杂度下限了。

 

Yzf说这种思想可以用来解决poj上边的一道互相说谎,但是保证说真话的人超过一半的问题。我没有见过这道题,不过我觉得这个简单的解题思路跟巧妙,值得记下来。

 

对于上面的第二中算法,如果数组为2 3 3 3 2 2 2 ,则找出的数为3,而不是2。算法一过于复杂,因此我提出自己的算法。

 

首先考虑,我们采用快速排序中的一次快速排序将数组分为两部分,根据我们所选的基准数可能出现以下情况:

 (1)求的数即为选的基准数,则可以确定在排序后中间的数即为所求的数。因为,求的数出现次数大于数组长度的一半,因此,所有小于等于该数的元素的个数必然大于数组长度的一半。则中间的数组元素即为所求的数。

(2)求的数小于基准数,则求的数必排在基准数左边,由于求的数出现次数大于数组长度的一半,因此数组中间的元素必为所求的数。

(3)求的数大于基准数的情况同(2)。

 因此,采用一次快速排序算法对数组进行排列后,中间的数即为所求的数。

原创粉丝点击