Easy 169 - Majority Element
In this blog I will share a solution to the Majority Element problem.
題目連結
難度:Easy
給定一個大小為 n 的陣列 nums,找出其中出現次數超過 ⌊n/2⌋ 次的元素,稱為多數元素。你可以假設陣列非空,且多數元素一定存在。
example:
example:
限制
- n == nums.length
- 1 <= n <= 5 * 10^4
- -10^9 <= numsi <= 10^9
Array
Hash Table
Sorting
解題思路
思考過程
- 初步分析
- 需要找出出現次數超過一半的元素
- 這個元素一定存在
- 可能有多種解法
- 可能的解法
- 直觀解法:Map 計數:使用雜湊表 (O(n))
- 思考後的解法:排序解法:排序後取中位數 (O(n log n))
- leetcode 上看到的解法:Boyer-Moore 投票算法:O(n) 最優解
- 選擇理由
- 排序解法程式碼最簡潔
- 容易理解和維護
解法演進
1. 初始解法:使用 Map 計數
使用 Map 來追蹤每個數字出現的次數:
實作過程
- Map 計數解法
這是最直觀且常見的解法,將每個數字出現的次數計算出來,並且比較是否超過一半,如果超過一半則返回該數字,但我自己認為這個寫法有稍微複雜了一點
- 排序解法:自己比較偏好這個寫法,因為可讀性高且效能也不會太差
注意:雖然這個解法程式碼最簡潔,但時間複雜度是 O(n log n),如果需要最優的時間複雜度, 可以考慮使用 Boyer-Moore 投票算法(O(n))。
Boyer-Moore 投票算法
這是一個非常巧妙的算法,核心思想是:
- 如果一個數是多數元素,那麼它出現的次數減去其他所有元素出現的次數仍然大於 0
算法步驟說明
為什麼這個算法有效?
- 如果 count 變為 0,表示目前的 candidate 和其他元素抵消
- 多數元素出現次數 > n/2,所以最後一定會勝出
- 時間複雜度 O(n),空間複雜度 O(1)
複雜度分析
讓我們比較三種解法的複雜度:
解法 | 時間複雜度 | 空間複雜度 | 優缺點 | 適用場景 | 技巧 |
---|---|---|---|---|---|
Map 計數 | O(n) | O(n) | 效能較好,但程式碼較複雜 | 小規模 | 使用 Map 計數 |
排序解法 | O(n log n) | O(n) | 直觀易懂,但效能較差 | 小規模 | 使用 toSorted() 排序 |
Boyer-Moore 投票算法 | O(n) | O(1) | 效能最好,但較難理解 | 大規模 | 使用投票算法 |
實際應用
這個問題在實際開發中有很多應用場景:
- 投票系統:找出獲得過半數票的選項
- 圖像處理:找出主要顏色 (過去實作過去分析圖片上的像素顏色,並且進行排列,也是用很類似的方式)