Majority Element出现次数超过一半的数字

Given an array of size n, find the majority element. The majority element is the element that appears more than ⌊ n/2 ⌋ times.

You may assume that the array is non-empty and the majority element always exist in the array.

这是一道编程之美和剑指offer上都有的题目。

直观的思路先对数组进行排序,则中间index上存储的数一定是该出现次数超过一半的数字。但是这种操作的时间复杂度为为排序的时间复杂度O(nlogn),不是很理想。

另外一种思路是思路是对快排的改进,即我们不需要对数组进行彻底排序,只需要找到那个在最终排序完的数组中的中间index的那个元素。使用QuickSort的partition来完成这种任务很合适。每次partition会找到 pivot所在的index,可以通过不断二分选择,使最终的pivot的index为(left+right)/2达到目的。

算法时间复杂度平均情况下为O(n)。也是devide and conquer分治的思想。

另外一种思路是既然该数字在数组中出现次数超过一半,则该数字的出现次数比其他所有数字的次数都多。则每次删除数组中两个不同的数,留下的数组中该数字的出现次数依然超过一半。

具体实现时并不是真正去两两删除,而是用一个times和一个result来模拟。result保存数组中的数字,times保存出现的次数。如果下一个数字和我们保存的result中的值不一样,则times的值减1,否则times加1,如果当前times为0,则将result的值赋为当前值,最终result的值为那个出现出现次数超过一半的数的值。代码如下:

class Solution(object):
    def majorityElement(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        times = 1        #开始times初始化
        result = nums[0] #
        for i in nums[1:]:
            if times == 0:
                result = i #重新开始
                times = 1  #重新开始计数
            else:
                if result == i:
                    times += 1
                else:
                    times -= 1
        return result

注意如何把这段代码和两两删除不同的元素对应上。实际上从result赋值,times为1,到times降为0这个过程,实现的就是删除元素的过程。比如1234,1到2时,times为0,3时times重新等于1,record为3,4时times又降为0,其实就是两两删除的过程。如果有连续值,555534216,则到1时,times也降为0,相当于(5,3),(5,4),(5,2),(5,1)两两删除了。所以在最后一个 times为1,record换值时,record就是那个出现超过一半的数字,一直到数组尾部,也没有那么多和record不同的元素来和它抵消。算法成立。

posted on 2016-05-09 15:59  Sheryl Wang  阅读(213)  评论(0编辑  收藏  举报

导航