演算法 摩爾投票

2022-07-15 08:21:13 字數 2112 閱讀 9227

【摩爾投票】

問題: (majority element)若有乙個陣列l,長度為n,找出是否有乙個數n,n的出現次數大於等於n/2。

問題不算太難,一般可以通過遍歷計數,或者排序找中位數的辦法來解決。但是如果要求時間複雜度是o(n),空間複雜度是o(1),那麼恐怕就沒那麼簡單了。摩爾投票演算法正好是這麼乙個o(n)和o(1)的演算法。

●  描述

宣告m=0和cnt=0兩個變數後面用。

遍歷陣列,當cnt為0時將當前遍歷到的元素賦值給m,然後cnt+=1。若cnt不為0,且遍歷到的元素等於當前的m,那麼cnt += 1,;若cnt不為0,但是遍歷到的元素也不等於當前的m,那麼cnt -= 1。最終遍歷完成之後,變數m的值就是我們要找的那個majority element。

為什麼這個演算法奏效?我們姑且從感性的角度來理解一下。既然是投票,那麼就把這個陣列yy成乙個投票人的集合。這些投票人心中都有自己想要投的人,然後我們要找出的就是哪個候選人得票能過半的。因為我們無法做到同時聽取所有人的想法,所以我們採取一種「淘汰制」選擇。首先第乙個人上台說明他想要推舉的候選人比如說a。如果第二個人也是推舉a的,那麼可以認為a的人氣是兩人份的。第三人如果不是推舉a的,那麼他將減少a的乙份人氣。因為選舉是要求最終得票過半,所以對於候選人a來說,每乙個人不投票給他,就相當於他損失了一票。若第四人也不投a,則a的人氣歸零,和其他候選人重回起跑線,但此時站在候選台上的仍然是a。此時第五人若想就可以推舉他想選的人b,把a給擠下來,b的人氣為1。以此類推… 從大局上講,如果a的支持者勢力足夠強大,那麼無論a被打倒多少次,最終還是能夠回到候選台上。這邊勢力強大的具體量化就是a的支持者至少達到n/2人。這樣即使前一半人都支援a,後一半人都不支援a,最終a的人氣歸零,但是還是保證站在候選台上的是a。

上面就是對投票演算法的乙個粗淺且感性的理解。

●  **:

def

vote(a):

m,cnt =0,0

for n in

a:

if cnt ==0:

m =n

cnt = 1

elif n ==m:

cnt += 1

else

: cnt -= 1

return m

上述過程中並沒有對投票者支援的人非常分散的情況作出判斷。即無法完成選舉的時候不會給出無法完成的錯誤,而是返回了接近陣列末尾的某個「勢力相對較強」的元素。如果需要對是否超過n/2做判斷那麼可以再去遍歷依次陣列,看到底m元素出現了幾次,是否達到標準即可。

●  更複雜一點

如果將問題換成,找出所有出現次數大於n/3次的元素呢。顯然,這種元素最多只能有兩個。所以我們可以使用投票演算法,將有可能是符合要求的兩個元素找出來,然後再看他們是否都超過了n/3來判斷是否選擇它們作為需要選出來的元素。

具象到選舉中來,那麼可以認為現在要選的人是兩個。而且這兩個人競選的位置是平級,不分先後的,所以熱門候選人a和熱門候選人b的支持者之間不構成直接競爭。因此,演算法就變成了,第一人推薦a,a走上甲候選臺。第二人推薦b,b走上乙候選臺,而此時對a不構成影響所以a的人氣不減。如果第三人推薦的是c,那麼a和b的人氣都要減乙份,都歸零了(顯然不能只減乙個人的人氣,否則另乙個人就可能會出現明明支持者很少,但是由於推舉的順序比較靠前所以當選的bug)。如果此時第四人支援的不是a或者b而是d,那麼就可以從甲乙任意乙個候選臺中擠走乙個。比如擠走a,之後d的人氣是1,而另乙個候選台上的b仍然是0人氣。這麼迴圈下去,由於a和b不互相競爭,所以通過這個演算法得到的a和b是所有候選人中相對強勢的兩個。

**的實現也不複雜:

def

vote(a):

m,n =0,0

cm,cn =0,0

for i in

a:

if cm == 0: m = i; cm += 1

elif cn == 0: n = i; cn += 1

elif i == m: cm += 1

elif i == n: cn += 1

else: cm -= 1; cn -= 1

return m,n

* 其實摩爾投票,主要是為了能夠在o(n)的時間和o(1)的空間解決問題。如果沒有這些限制,那麼使用hashmap或者其他的一些什麼方法則要比這種方法好理解得多多。

摩爾投票演算法

在它最簡單的形式就是,查詢最多的元素,也就是在輸入中重複出現超過一半以上 n 2 的元素。如果序列中沒有最多的元素,演算法不能檢測到正確結果,將輸出其中的乙個元素之一。當元素重複的次數比較小的時候,對於流演算法不能在小於線性空間的情況下查詢頻率最高的元素。假設這個陣列中共有n個元素,我們可以把數值不...

演算法 摩爾投票

摩爾投票 問題 majority element 若有乙個陣列l,長度為n,找出是否有乙個數n,n的出現次數大於等於n 2。問題不算太難,一般可以通過遍歷計數,或者排序找中位數的辦法來解決。但是如果要求時間複雜度是o n 空間複雜度是o 1 那麼恐怕就沒那麼簡單了。摩爾投票演算法正好是這麼乙個o n...

摩爾投票演算法

思路一 使用map集合,記錄元素的出現次數 class solution return 0 思路二 用到的演算法是 摩爾投票演算法 演算法在區域性變數中定義乙個序列元素 value 和乙個計數器 count 初始化的情況下計數器為0.演算法依次掃瞄序列中的元素,當處理元素x的時候,如果計數器為0,那...