陣列入門題 用BM投票演算法 找超過n/3的領先者 Majority Element II Leetcode #229

更新於 發佈於 閱讀時間約 5 分鐘
raw-image

這題的題目在這裡:

題目敘述

題目會給定我們一個陣列,陣列長度為n。
要求我們找出裡面出現次數超過 n / 3次的數字


測試範例

Example 1:

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

Example 2:

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

Example 3:

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

約束條件

Constraints:

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

 Follow up: Could you solve the problem in linear time and in O(1) space?


演算法

如果只是第一直覺的話,第一輪掃描先用字典來統計出現次數,第二輪再挑選出現次數超過 n/3次的元素即可。

但是,這題其實也可以用前一題學過的Bayer Moore投票演算法的模板來解。

第一輪選舉輪,先選出票數領先的前兩人

第二輪驗證輪,驗票,檢驗領先的前兩人是否票數有超過n/3,若有,則放入最後的當選名單。

實作上有一個小細節,為什麼我們只需要選出領先的前兩人?
因為題目的規則是要超過n/3,透過簡單的反證法,可以證出最多只會有兩人有機會超過n/3

推廣題: 若題目改成超過n/k,則最多只會有(k-1)人有機會超過 n/k


程式碼

class Solution:
 def majorityElement(self, nums: List[int]) -> List[int]:
  
  # a list of majority elements
  majority = []
  
  # threshold for majority validation and verification
  threshold = len(nums) // 3
  
  # Record for possible majority candidates, at most two majority elements is allowed by math-proof.
  candidate = [0, 0]
  
  # Voting for majority candidates
  voting = [0, 0]
  
  ## Step_#1:
  # Find possible majority candidates
  for number in nums:
   
   if number == candidate[0]:
    # up vote to first candidate
    voting[0] += 1
    
   elif number == candidate[1]:
    # up vote to second candidate
    voting[1] += 1
   
   elif not voting[0]:
    # set first candidate
    candidate[0] = number
    voting[0] = 1
    
   elif not voting[1]:
    # set second candidate
    candidate[1] = number
    voting[1] = 1
    
   else:
    # down vote if mis-match
    voting[0] -= 1
    voting[1] -= 1
  
  
  ## Step_#2:
  # Validation:
  voting = [0, 0]
  
  for number in nums:
   
   if number == candidate[0]:
    # update up vote for first candidate
    voting[0] += 1
    
   elif number == candidate[1]:
    # update up vote for second candidate
    voting[1] += 1
  
  
  for i, vote in enumerate(voting):
   
   # Verify majority by threshold
   if vote > threshold:
    majority.append( candidate[i] )
   
   
  return majority

複雜度分析

時間複雜度:

O( n ) 投票輪和驗證輪,複雜度皆為線性,各掃描一次。

空間複雜度:

O(1) majority, voting, candidate都是臨時變數,所占用的記憶體空間固定,都是常數級別O(1)


關鍵知識點

關鍵點在於聯想到用BM投票演算法找出領先者。

前一題,我們用BM投票演算法找出票數最多的那一位,也稱之為眾數 mode。

在這一題,我們用BM投票演算法找出票數相對多的前k位,k=2,同時門檻票數要求超過 n/3


Reference:

[1] Python O(1) aux space sol. by BM vote algorithm. [ With explanation ] - Majority Element II - LeetCode

avatar-img
90會員
425內容數
由有業界實戰經驗的演算法工程師, 手把手教你建立解題的框架, 一步步寫出高效、清晰易懂的解題答案。 著重在讓讀者啟發思考、理解演算法,熟悉常見的演算法模板。 深入淺出地介紹題目背後所使用的演算法意義,融會貫通演算法與資料結構的應用。 在幾個經典的題目融入一道題目的多種解法,或者同一招解不同的題目,擴展廣度,並加深印象。
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
題目會給定我們一個輸入陣列,裡面的字母A和字母B分別代表兩種顏色的卡片。 假如某張卡片的左右都是相同的,例如AAA,Alice可以抽掉中間那張A。 同樣的,假如某張卡片的左右都是相同的,例如BBB,Bob可以抽掉中間那張B。 請問Alice和Bob輪流玩抽卡遊戲, 請問最後是誰贏?
題目給定一個已排序的輸入陣列,陣列裡面的數字自分別代表每篇論文的被引用數。 要求我們計算h-index。 h-index的定義: 找一個最大的h值,使得有h篇論文,個別論文的被引用數都 大於等於 h
題目給定一個輸入陣列,陣列裡面的數字自分別代表每篇論文的被引用數。 要求我們計算h-index。 h-index的定義: 找一個最大的h值,使得有h篇論文,個別論文的被引用數都 大於等於 h
題目會給定兩個參數,一個是底數x,一個是次方n。要求我們計算出x^n。 要求實作myPow(self, x: float, n: int) -> float 函數的內部邏輯。 也就是說,不可以呼叫程式語言內建計算指數的library
1. 競賽題 或者 面試題 Medium Hard 以上題目,一開始在第一時間想不出解題思路,或者最佳解是很平常的事情。 通過官方解答、討論區的高手分享解題,進而學到新的解題思路,或者更泛用的演算法框架,就是最大的收穫。 2. 但是Easy分類的題目,通常就是該領域最基礎的題目,應該要
題目會給定我們一個陣列,要求我們找出裡面出現次數最多的數字。 出現次數最多的數字也就是我們在統計上所謂的 眾數 mode
題目會給定我們一個輸入陣列,裡面的字母A和字母B分別代表兩種顏色的卡片。 假如某張卡片的左右都是相同的,例如AAA,Alice可以抽掉中間那張A。 同樣的,假如某張卡片的左右都是相同的,例如BBB,Bob可以抽掉中間那張B。 請問Alice和Bob輪流玩抽卡遊戲, 請問最後是誰贏?
題目給定一個已排序的輸入陣列,陣列裡面的數字自分別代表每篇論文的被引用數。 要求我們計算h-index。 h-index的定義: 找一個最大的h值,使得有h篇論文,個別論文的被引用數都 大於等於 h
題目給定一個輸入陣列,陣列裡面的數字自分別代表每篇論文的被引用數。 要求我們計算h-index。 h-index的定義: 找一個最大的h值,使得有h篇論文,個別論文的被引用數都 大於等於 h
題目會給定兩個參數,一個是底數x,一個是次方n。要求我們計算出x^n。 要求實作myPow(self, x: float, n: int) -> float 函數的內部邏輯。 也就是說,不可以呼叫程式語言內建計算指數的library
1. 競賽題 或者 面試題 Medium Hard 以上題目,一開始在第一時間想不出解題思路,或者最佳解是很平常的事情。 通過官方解答、討論區的高手分享解題,進而學到新的解題思路,或者更泛用的演算法框架,就是最大的收穫。 2. 但是Easy分類的題目,通常就是該領域最基礎的題目,應該要
題目會給定我們一個陣列,要求我們找出裡面出現次數最多的數字。 出現次數最多的數字也就是我們在統計上所謂的 眾數 mode
你可能也想看
Google News 追蹤
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
這題是面試中常見的經典題目,要求從一個陣列裡找出出現次數超過一半的元素,也就是所謂的「眾數」。為了更好理解,會先用一個直觀、易懂的方式來解釋問題,透過哈希表的方法來找出答案。接著,我會介紹一個更快、更有效率的解法,也就是 Boyer-Moore 多數投票算法。
Thumbnail
計數原理的題目們,以及上次排組的解析。
Thumbnail
在看完了咚咚的思辨學堂老師的機率的排列組合 – 在數學上要多加留意題目裡的「換句話說」後。 那題代數轉塗色問題我是真的沒想到。(學會了!😆😆😆) 我決定我也來出幾題。 難度稍高? 邀請大神一同作答激盪出不同的解法。 (一)5對兄妹共舞,若每一兄均不與其妹為舞伴,則共有      
Thumbnail
分享在網路上看到的陣列題目。通常 for...of 的 value 是陣列中的每個值,那如果我們在迭代中對陣列操作會發生什麼事? 題目來源:https://x.com/_jayphelps/status/1774640511158022335?s=20
Thumbnail
不同的運算子一起出現時,會根據其優先性(Precedence)來決定誰先誰後。MDN也很貼心的整理成表格了。 雖然有表格可以供我們查找,但是總不可能每一次用到運算子的時候,我們都去查找吧?我們最好對這張表有直觀上的理解與記憶。 那麼就讓我來分享我如何理解與記憶這張表吧! 運算子在做甚麼
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
這題是面試中常見的經典題目,要求從一個陣列裡找出出現次數超過一半的元素,也就是所謂的「眾數」。為了更好理解,會先用一個直觀、易懂的方式來解釋問題,透過哈希表的方法來找出答案。接著,我會介紹一個更快、更有效率的解法,也就是 Boyer-Moore 多數投票算法。
Thumbnail
計數原理的題目們,以及上次排組的解析。
Thumbnail
在看完了咚咚的思辨學堂老師的機率的排列組合 – 在數學上要多加留意題目裡的「換句話說」後。 那題代數轉塗色問題我是真的沒想到。(學會了!😆😆😆) 我決定我也來出幾題。 難度稍高? 邀請大神一同作答激盪出不同的解法。 (一)5對兄妹共舞,若每一兄均不與其妹為舞伴,則共有      
Thumbnail
分享在網路上看到的陣列題目。通常 for...of 的 value 是陣列中的每個值,那如果我們在迭代中對陣列操作會發生什麼事? 題目來源:https://x.com/_jayphelps/status/1774640511158022335?s=20
Thumbnail
不同的運算子一起出現時,會根據其優先性(Precedence)來決定誰先誰後。MDN也很貼心的整理成表格了。 雖然有表格可以供我們查找,但是總不可能每一次用到運算子的時候,我們都去查找吧?我們最好對這張表有直觀上的理解與記憶。 那麼就讓我來分享我如何理解與記憶這張表吧! 運算子在做甚麼