Description

給定大小為 n 的陣列 nums,回傳多數元素。多數元素是出現次數超過 n/2 的元素。保證多數元素一定存在。

Example:

Input: nums = [2,2,1,1,1,2,2] Output: 2

Intuition#

核心思路:Boyer-Moore 投票演算法——把多數元素看作「票數最多的候選人」,用 +1/-1 計票。

  • 因為多數元素超過 n/2 次,其他所有元素加起來也不足以「抵銷」它
  • 維護候選人和計數器,相同 +1、不同 -1,歸零時換候選人

Approaches#

1: HashMap 計數#

  • 概念: 用 HashMap 統計每個元素的出現次數,找出超過 n/2 的
  • 時間複雜度: O(n) - 遍歷一次
  • 空間複雜度: O(n) - HashMap 儲存
class Solution {
    fun majorityElement(nums: IntArray): Int {
        val count = HashMap<Int, Int>()
        for (num in nums) {
            count[num] = (count[num] ?: 0) + 1
            if (count[num]!! > nums.size / 2) return num
        }
        throw IllegalArgumentException()
    }
}

⭐2: Boyer-Moore Voting Algorithm#

  • 概念: 維護候選人 candidate 和計數器 count,遇到相同元素 +1,不同 -1,歸零時更換候選人
  • 時間複雜度: O(n) - 一次遍歷
  • 空間複雜度: O(1) - 只用兩個變數
class Solution {
    fun majorityElement(nums: IntArray): Int {
        var candidate = nums[0]
        var count = 0
        for (num in nums) {
            if (count == 0) candidate = num
            count += if (num == candidate) 1 else -1
        }
        return candidate
    }
}
補充:排序法

排序後,多數元素一定出現在中間位置 nums[n/2]

class Solution {
    fun majorityElement(nums: IntArray): Int {
        nums.sort()
        return nums[nums.size / 2]
    }
}

時間 O(n log n),空間 O(1)(原地排序)。

🔑 Takeaways#

  • Pattern: Boyer-Moore Voting 是找多數元素的經典 O(1) 空間演算法
  • 關鍵技巧: 核心直覺是「多數元素的票數永遠不會被完全抵銷」;此演算法可推廣到出現超過 n/3 次的元素(LC 229)