陣列入門題 用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

52會員
339內容數
由有業界實戰經驗的演算法工程師, 手把手教你建立解題的框架, 一步步寫出高效、清晰易懂的解題答案。 著重在讓讀者啟發思考、理解演算法,熟悉常見的演算法模板。 深入淺出地介紹題目背後所使用的演算法意義,融會貫通演算法與資料結構的應用。 在幾個經典的題目融入一道題目的多種解法,或者同一招解不同的題目,擴展廣度,並加深印象。
留言0
查看全部
發表第一個留言支持創作者!
你可能也想看
震驚全球的奧斯卡send tree pay事件背後,其實有許多值得我們思考的議題!隨著奧斯卡的落幕, 這一巴掌響出天際成為熱門題材, 成為大家爭相討論模仿的話題, 但其實這背後也帶出許多的議題討論 2022年第94屆奧斯卡頒獎典禮上,喜劇演員—克里斯洛克(Chris Rock) 在舞台上大開威爾史密斯(Will Smith)的妻子 便衝上台給了克里斯一個響亮的巴掌,
Thumbnail
avatar
zoe搜世界
2022-04-02
【震驚了!孔字的次元切割刀?】「漢字切割刀」也能造字?不是只有靠著六書才能造字嗎? 沒錯,漢字世界造字可不只有六書而已,花招不少,是時候該進化一下了!
Thumbnail
avatar
野蠻小邦周之方格子分舵
2020-05-24
「震」出的美食小舖地震後的石岡鄉滿目瘡痍、百業蕭條,整體環境只能用破碎來形容。地震震垮了農村道路橋樑等基礎建設,也損毀了農村土地及農作,地方產業生產工具陷入崩解,連帶使得原本就業機會不多的鄉鎮雪上加霜。
Thumbnail
avatar
NYCU PRESS說書中(陽明交大出版社)
2020-03-12
震盪效應 觀後感   "震盪效應"算是蠻典型的非主流小人物對抗主流社會的題材,最終雖然獲得肯定,但卻沒有獲得主角預設的效應。   男主角Omalu有著典型的非主流特徵:非名校且又來自落後國家/有色人種/關心死者生前的生活/不預設立場等等,正因為如此,他發現到美式足球對於腦部的傷害,遠超乎當代的認知,也因為對於真相的
avatar
關欣
2019-09-29
震災與財物 / 2000.02.25.因為發生地震,住家的整棟房子突然大幅度的傾斜,我也在睡夢中驚醒過來。 我下床到樓頂上去察看,發現同一棟樓許多鄰居家的陽台都崩塌了,看來震災損害相當嚴重。 由於整棟房子已經變成危樓,勢必要拆除重建,於是 ......
Thumbnail
avatar
羅聖爾
2019-02-21
【鎮島忠臣王副校】東亞地區自古便有一種習俗是以活人為建築物奠基;古人相信只要把人活埋進地基便可以強制被埋者成為這座建築的守護神, 從而令工程得以順利完成。 據說在日本這種習俗名為「人柱」, 在 「#中國」 則名為「#打
Thumbnail
avatar
香港新中史學社
2019-01-30
振興經濟的根本振興經濟的根本是甚麼呢?先想一件事,財富是甚麼?簡單地說,財富就是你想要的東西。而倒轉來說,負債就是你不想要的東西。「錢」只是一種將這些東西量化、而方便計算及交換的工具。如果不僅記這三點,就不可能理解經濟。
Thumbnail
avatar
鄭立
2018-12-18
震盪市場,各種投資參考(下):內含500萬學費儲蓄險、基金、股票、房地產 選擇權、虛擬貨幣、資金盤 (HYIP) 美股、黃金、外匯、期貨、CMS 上述站長都接觸過了,賠了500多萬 如果這短文能拯救更多朋友 500萬絕對值得
Thumbnail
avatar
乃皇包
2018-11-12
震盪市場,各種投資參考 (上)投資年齡來到9歲 正巧遇到10年大關 看著越來越多"老師"被打臉 站長也一直在實現損益 希望這次退潮 站長不要是裸體的那個 😂
Thumbnail
avatar
乃皇包
2018-11-05