刷无悔 169 ~ 主要元素

土豆炒青椒
·
·
IPFS
刷爆 leetcode,做有追求的码工

基本信息

  • 题号:169
  • 题厂:脸书
  • 难度系数:低



数组里面有一个数出现次数是数组长度一半以上,即数组主要元素。

问:把主要元素找出来……

例如:nums = [3,2,3]

3 是主要元素,返回 3


解题思路

  • 计算出现次数这种事,一般都靠 hashmap 辅助。
  • 本题如果靠 hashmap,当 count 计数超过一半时就返回。
  • 一半上限,即 数组长度 / 2



class Solution:
    def majorityElement(self, nums: List[int]) -> int:
        if len(nums) == 1:
            return nums[0]
        
        half = len(nums) // 2
        counter = {}
        
        for num in nums:
            counter[num] = 1 + counter.get(num, 0)
            
            if counter[num] > half:
                return num

靠以上 hashmap 计数的解法,我们在 5 分钟内击败了 85% 的解法,然而本题还有后续🐮

如何使用 O(1)的空间利用率解决问题???!!!

如果要用 O(1)解决空间利用率,意味着 hashmap 这种数据结构无法登场。所以请出了超高级的人名算法——Boyer-Moore 🤪

题目确定了已知数组一定有主要元素(出现次数超过一半),[2,1,3] 这种无主要元素的状况不会出现,于是引用 Boyer-Moore 解题。简单理解就是:

  • 如果当前计数器为 0, 就初始化返回值为当前元素;
  • 如果当前元素和返回值相等,计数器 +1;
  • 如果当前元素和返回值不等,计数器 -1;
  • 因为主要元素出现次数超过一半,能把计数器清零后在获得重置权的肯定就只有主要元素了……所以这样一来,当 for 循环遍历完成后,返回值一定就是当前数组主要元素😵

Constraints

  • n == nums.length
  • 1 <= n <= 5 * 104
  • -109 <= nums[i] <= 109

考试时可以向考官确认主要元素到底存不存在,需不需要考虑不存在情况🙈


Big O

  • Time:O(n)
  • Space:引入 hashmap 为 O(n);Boyer-Moore 最优解为 O(1)


测试

  • 数组为 1 时
  • 主要元素插空出现
  • 主要元素在开头出现
  • 主要元素在末尾出现
  • 次要元素有一个多个值
  • ……



总结

  • 本题如果就是 hashmap 计数,这是一道 10 分钟内即可搞定的简单题;
  • 最优解法 Boyer-Moore 虽然代码依然简单,但算法小白是一定不可能想出来的,所以最优解甚至可以归为难挡😭
  • 考试时当你第一时间完成了 hashmap 解法后,考官一定还会问你有没有其他解法,优化解法(此处即算法小白几乎不可能想出的 Boyer-Moore)……😭



更多Boyer-Moore 强大介绍 🙈:

https://www.geeksforgeeks.org/boyer-moore-majority-voting-algorithm/

CC BY-NC-ND 2.0 授权

喜欢我的作品吗?别忘了给予支持与赞赏,让我知道在创作的路上有你陪伴,一起延续这份热忱!