Featured image of post [筆記] Boyer-Moore Majority Voting

[筆記] Boyer-Moore Majority Voting

Boyer-Moore majority voting 演算法

問題

您可能會看到一些問題要求計算某人的選票超過 1/2 或 1/3。直覺的解決方案是為每個人計票。然而,空間複雜度將為 O(N)。是否有任何解決方案僅使用 O(1) 來解決空間複雜度?這將是 Boyer-Moore Majority Voting 演算法。

基本想法

如果我們知道至少有一個人獲得了 1/2、1/3 或 1/n 選票,我們可以刪除 n 張不同的選票,並且不會影響結果。

例如,我們有三個候選人 (A、B、C),A 是獲得至少 1/2 選票的候選人。所以,我們可以去掉不同候選人的 2 張不同的選票,並且不會影響 A 至少有 1/n 選票。

  • 刪除 (B, C): 不影響 A 超過 1/2 的票。這會讓A的百分比成長。
  • 刪除 (A,C): 刪除最多的一個和另一的一個。不會影響 A 票數大於 1/2 的事實。
  • 刪除 (A,B): 刪除最多的一個和另一的一個。不會影響 A 票數大於 1/2 的事實。

如上所述,當使用 Boyer-Moore majority voting 演算法時,我們需要找到 n 個不同的票並刪除或忽略它們。儲存 n 票僅花費 O(1) 空間。

以下程式碼計算得票數超過了 floor(n/3) 的候選人。這是來自 Leetcode 的問題 229. Majority Element II

vector<int> majorityElement(vector<int> &nums) {
    int x = 0, y = 0, cX = 0, cY = 0;

    for (const auto & n: nums) {
        if (n == x)
            cX++;
        else if (n == y)
            cY++;
        else if (cX == 0) {
            x = n;
            cX = 1;
        } else if (cY == 0) {
            y = n;
            cY = 1;
        } else {
            cX--;
            cY--;
        }
    }

    cX = 0;
    cY = 0;
    for (const auto & n: nums) {  
        if (n == x) 
            cX++;
        else if (n == y) 
            cY++;
    }

    vector<int> res;
    if (cX > nums.size() / 3) 
        res.push_back(x);
    if (cY > nums.size() / 3) 
        res.push_back(y);
    return res;
}

如果你有任何問題,歡迎透過 Email 與我聯絡,或是在底下留言,謝謝。

comments powered by Disqus
使用 Hugo 建立
主題 StackJimmy 設計