169. Majority Element [easy] (Python)

题目链接

https://leetcode.com/problems/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.

题目翻译

给定一个大小为n的数组,找到其中的“多数元素”。多数元素指的是出现次数超过 ⌊ n/2 ⌋ 次的元素。
假定数组非空,且给定的数组中一定存在多数元素。

思路方法

首先,暴力双循环是一个方法,但复杂度太高不可取。这道题的解法非常多,下面我实现了一些,有兴趣的可以再搜搜别的方法和实现。

附LeetCode解决建议(若图片看不清,请右键图片在新标签页打开查看):
《169. Majority Element [easy] (Python)》

思路一

(HashTable)遍历数组,用一个字典记录所有出现过的元素及其个数。由于题目说明多数元素一定存在,故当找到某个元素出现次数大于 ⌊ n/2 ⌋ 时即可停止。

代码一

class Solution(object):
    def majorityElement(self, nums):
        """ :type nums: List[int] :rtype: int """
        digits = {}
        for i in nums:
            digits[i] = digits.get(i, 0) + 1
            if digits[i] > len(nums)/2:
                return i

类似的,也可以考虑用集合这一数据结构。先找出数组中的所有不同的数,相当于“取原数组的集合”的操作,然后判断该集合中的每个数在数组中出现次数是否过半。

代码二

class Solution(object):
    def majorityElement(self, nums):
        """ :type nums: List[int] :rtype: int """
        nums_set = set(nums)
        for i in nums_set:
            if nums.count(i) > len(nums)/2:
                return i

思路二

(Sort)先对数组进行排序,因为多数元素一定存在,且个数超过总个数的一半,那么排序后最中间的那个元素一定是多数元素。

代码

class Solution(object):
    def majorityElement(self, nums):
        """ :type nums: List[int] :rtype: int """
        nums.sort()
        return nums[len(nums)/2]

思路三

(Randomization)这个方法听起来不是很靠谱,平均复杂度O(n),最差复杂度无穷大,但实际运行还是挺稳定的。其方法是,随机抽一个元素,检查是否是多数元素,由于多数元素个数占大半,期望查找次数<2。

代码

class Solution(object):
    def majorityElement(self, nums):
        """ :type nums: List[int] :rtype: int """
        import random
        while True:
            r = random.choice(nums)
            if nums.count(r) > len(nums)/2:
                return r

思路四

(Divide and Conquer)分治法。每次将数组分成左右两半,在两半中分别找出现次数最多的元素,若找到的两个元素相同则此元素即为所求,否则在整个数组中分别计算这两个元素出现的次数,取较大的那个。

代码

class Solution(object):
    def majorityElement(self, nums):
        """ :type nums: List[int] :rtype: int """
        return self.major(nums, 0, len(nums)-1)

    def major(self, origin_nums, left, right):
        if left == right:
            return origin_nums[left]
        mid = (left + right) / 2
        major_l = self.major(origin_nums, left, mid)
        major_r = self.major(origin_nums, mid+1, right)
        if major_l == major_r:
            return major_l
        return major_l if origin_nums[left: right+1].count(major_l) > origin_nums[left: right+1].count(major_r) else major_r

思路五

(Moore Voting Algorithm)该算法的思想是:每次都找出一对不同的元素,从数组中删掉,直到数组为空或只有一种元素。 不难证明,如果存在元素e出现频率超过半数,那么数组中最后剩下的就只有e。

代码

class Solution(object):
    def majorityElement(self, nums):
        """ :type nums: List[int] :rtype: int """
        major = count = 0
        for i in nums:
            if count == 0:
                major = i
                count = 1
            else:
                count += 1 if major == i else -1
        return major

思路六

(Bit Manipulation)既然存在所谓大量元素,那么倘若我们将所有的数写成二进制,每个数写一行进行位对齐,那么每一位出现最多的0或1就是大量元素在该位的值。基于这个想法,考虑到题目说的是整数(32位),我们可以统计每一位出现次数最多的0或1,组合即得。
需要注意的是,因为Python对于整数的处理太过方便,当LeetCode的测试程序给出负数(即最高位为1的32位整数)时,用Python进行位处理最终得到的却是正数,所以需要对负数做特殊处理。

代码

class Solution(object):
    def majorityElement(self, nums):
        """ :type nums: List[int] :rtype: int """
        major = 0
        mask = 1
        for i in xrange(0, 32):
            count = 0
            for j in nums:
                if j & mask:
                    count += 1
                    if count > len(nums)/2:
                        major |= mask
                        break
            mask <<= 1

        return major if major>>31 == 0 else major - (1<<32)

PS: 新手刷LeetCode,新手写博客,写错了或者写的不清楚还请帮忙指出,谢谢!
转载请注明:http://blog.csdn.net/coder_orz/article/details/51407713

    原文作者:coder_orz
    原文地址: https://blog.csdn.net/coder_orz/article/details/51407713
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞