理解摩爾投票法

算法題目:數組中有一個數字出現的次數超過數組長度的一半,請找出這個數字(數組非空,一定存在這個數字)。

 摩爾投票法算法的本質思想就是:抵消,抵消,抵消,到不能再抵消爲止。

首先,我們先來了解一下是如何抵消的,抵消就是讓數組中任意兩個不同的元素進行抵消,一直抵消到最後剩下的就是出現次數唱過數組長度一半的數字了;具體的我們可以舉一個例子來說明一下,給定的數組爲{ 1, 2, 3, 2, 2, 2, 5, 4, 2 },具體抵消的過程爲:

  1. 先聲明一個數組array,用來存放當前無法抵消的數字;
  2. 遍歷題目中給定的數組;第一個元素爲 1,此時數組array爲空,裏面沒有元素能夠與 1 相互抵消,所以將 1 存入到數組中;
  3. 第二個元素爲 2,此時數組array中存在一個 1 可以與 2 相互抵消,抵消之後數組array又變爲空;
  4. 後面兩個元素 3 和 2,也可相互抵消;遍歷到第7個元素 5 的時候數組array爲{ 2,2 },這時元素 5 可以與數組array中的任意一個 2 相互抵消,這裏不用考慮與哪個 2 進行抵消;
  5. 繼續遍歷到最後,會發現數組array中僅剩一個 2,所以這個數字就是 2;

上面這個是摩爾投票法的具體流程,接下來我們就要考慮對其進行優化;可能大家會發現數組array的作用好像並不是很大,而且數組中存儲的元素都只有一種,因爲如果有與數組中元素不同的數字就會產生抵消,不會進行存儲,因此我們在實際算法中可以將其替換;使用變量 x 表示數組array中存儲的元素,變量votes存儲的是其未被抵消的次數,具體思想和上面一樣在此就不再過多贅述,直接上代碼;

class Solution {
    public int majorityElement(int[] nums) {
        int x = 0, votes = 0;
        for(int num : nums){
            if(votes == 0)
                x = num;
            //如果遍歷到的元素num與存儲的元素x相等,則x存儲的次數+1,否則就-1
            num = num == x ? 1 : -1;
            votes += num;
        }
        return x;
    }
}

到這裏這個算法已經全部分享完畢,但是一定會有同學存在這種情況,這個算法的思路也都明白了,自己也會寫了,但是好像對不太理解爲什麼這樣就可以保證最後留下的就是出現的次數超過數組長度一半的那個元素?

這裏我再舉一個例子,玩一個諸侯爭霸類的遊戲,你放的人口超過了所有總人數的一半,而且保證每次打仗都時一換一的(你方死一個人一定會殺死一個敵人),最後還有人或者的國家勝利;這個時候怎麼辦 ?對,就是直接選擇大混戰,所有的管家出來一起打,哪怕是其他國家聯合打你一個,那麼最後生存的也一定是你,因爲你的人口超過了所有總人口的一半,即他們所有國家人加起來也沒你的國家人多;如果他們之間也相互攻擊,那豈不是更好了,所以只要你的國家不發生內鬥,最後贏的一定是你。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章