1. 程式人生 > >算法 - 摩爾投票算法

算法 - 摩爾投票算法

number algo code ray continue 時間 線性時間 .net blog

Boyer-Moore majority vote algorithm (摩爾投票算法)

典型案例:

(1) 找出大於n/2的元素,leetcode: https://leetcode.com/problems/majority-element/

class Solution {
    public int majorityElement(int[] nums) {
        int count = 0;
        int cur = 0;
        for(int i = 0; i < nums.length; ++i){
            if(count == 0){
                cur 
= nums[i]; count++; }else{ if(nums[i] == cur){ count++; }else{ count--; } } } return cur; } }

(2) 找出大於n/3的元素, letcode: https://leetcode.com/problems/majority-element-ii/

/*
    思路:摩爾投票升級版,超過n/3的數最多只能有兩個;
    先選出兩個候選人A,B,遍歷數組,如果投A(等於A),則A的票數++;如果投B,B的票數++;
    如果A,B都不投(即與A,B都不相等),那麽檢查此時是否AB中候選人的票數是否為0,如果為0,則成為新的候選人;
    如果A,B兩個人的票數都不為0,那麽A,B兩個候選人的票數均--;
    遍歷結束後選出兩個候選人,但是這兩個候選人是否滿足>n/3,還需要再遍歷一遍數組,找出兩個候選人的具體票數
     */
    public List<Integer> majorityElement(int
[] nums) { if (nums==null||nums.length==0){ return null; } //初始化,定義兩個候選人以及對應的票數 int candidateA=nums[0]; int candidateB=nums[0]; int countA=0; int countB=0; // 遍歷數組 for (int num:nums){ if (num==candidateA){ //投A countA++; continue; } if (num==candidateB){// 投B countB++; continue; } //此時A,B都不投,檢查是否有票數為0情況,如果為0,則更新候選人 if (countA==0){ candidateA=num; countA++; continue; } if (countB==0){ candidateB=num; countB++; continue; } //此時兩個候選人的票數都大於1,且當前選名不投AB,那麽A,B對應的票數都要--; countA--; countB--; } // 上一輪遍歷找出了兩個候選人,但是這兩個候選人是否均滿足票數大於N/3仍然沒法確定,需要重新遍歷,確定票數 countA=0; countB=0; for (int num:nums){ if (num==candidateA){ countA++; }else if (num==candidateB){ countB++; } } List<Integer> resultList=new ArrayList<>(); if (countA>nums.length/3){ resultList.add(candidateA); } if (countB>nums.length/3){ resultList.add(candidateB); } return resultList; }

Boyer-Moore majority vote algorithm(摩爾投票算法)是一種在線性時間O(n)和空間復雜度的情況下,在一個元素序列中查找包含最多的元素。它是以Robert S.Boyer和J Strother Moore命名的,1981年發明的,是一種典型的流算法(streaming algorithm)。

在它最簡單的形式就是,查找最多的元素,也就是在輸入中重復出現超過一半以上(n/2)的元素。如果序列中沒有最多的元素,算法不能檢測到正確結果,將輸出其中的一個元素之一。

當元素重復的次數比較小的時候,對於流算法不能在小於線性空間的情況下查找頻率最高的元素。

假設這個數組中共有n個元素,我們可以把數值不同的元素看做不同的群體成員(一個數字代表一個群體)。那麽我們現在要根據每個群在這個名單中各自的人數,使得在名單中出現人數最多的那個管理群。我們就先從數組的第一個元素開始,假定它代表的群體的人數是最多的,那麽根據數組中出現次數超過一半的數只有一個的特質,如果我們設置一個計數器,在遍歷時遇到不同於這個群體的人時就將計數器-1,遇到同個群體的人時就+1,只要在計數器歸0時就重新假定當前元素代表的群體為人數最多的群體再繼續遍歷(此時數據被分為兩段,前一段數據中被計數的元素數和numbers except it 數量是相等的,而後面的data中又滿足詞頻最高的數大於總數一半的情形,有點分治策略的思想),那麽到了最後,計數器記錄的那個群體必定是人最多的那個群體。這裏就使得元素排序是不會造成任何影響的,只關心元素的個數所帶來的對於計數器+1或-1的影響。

算法實現:

法在局部變量中定義一個序列元素(m)和一個計數器(i),初始化的情況下計數器為0. 算法依次掃描序列中的元素,當處理元素x的時候,如果計數器為0,那麽將x賦值給m,然後將計數器(i)設置為1,如果計數器不為0,那麽將序列元素m和x比較,如果相等,那麽計數器加1,如果不等,那麽計數器減1。處理之後,最後存儲的序列元素(m),就是這個序列中最多的元素。

典型的案例

(1)找出大於n/2的元素

(2)找出大於n/3的元素把兩個數轉化為一個數的思想,兩個大於n/3的肯定大於一半
---------------------
作者:碼農張學友
來源:CSDN
原文:https://blog.csdn.net/dpengwang/article/details/81710259
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!

算法 - 摩爾投票算法