1. 程式人生 > >LeetCode求眾數問題(摩爾投票法)

LeetCode求眾數問題(摩爾投票法)

今天刷到了一個求眾數的題目,講道理剛拿到這個題目,首先有點懵逼,確實想不到好的辦法去解決這個題目,後來看到評論有提示是摩爾投票法,我們來看看這個題目:
在這裡插入圖片描述
題目看似很簡單,但是很難找到思路,後來我學習了摩爾投票法,結合這道題目,發現眾數的個數一定是要大於整個陣列的1/2的,所以眾數的數量只有一個,這也是摩爾投票法的核心思想,我們解題的思路就是,將眾數和其他數進行相抵,到最後剩下的一定是眾數,僅僅從眾數的個數出發考慮,這道題就很簡單了。下面看看這道題的程式碼:

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

這段程式碼前面的部分就是將我們的眾數和非眾數進行相抵,如果相抵沒了,那麼就把陣列中的下一個數作為眾數進行相抵,最後相抵剩下的一定是這個陣列的眾數。看似很懵逼的一道題目,換個角度來想其實就很簡單了。
接下來還有一道求眾數的升級的題目,就是把眾數的閾值從1/2下降到1/3,這樣的話整個陣列就有可能有不止一個的眾數。我們來看看這道題目:
在這裡插入圖片描述
同樣的解法,只不過是變數多了一個,我們需要增加一個變數來計算我們的count,然後閾值是整個陣列的1/3就好了,整體解法和上一題相同。

public class Solution {
    public List<Integer> majorityElement(int[] nums) {
        List<Integer> res = new ArrayList<>();
        if(nums == null || nums.length == 0) return res;
        if(nums.length == 1) {
            res.add(nums[0]);
            return res;
        }
        int m1 = nums[0];
        int m2 = 0;
        
        int c1 = 1;
        int c2 = 0;
        
        for(int i=1; i < nums.length; i++) {
            int x = nums[i];
            if(x==m1) c1++;
            else if(x==m2) c2++;
            else if(c1==0) {
                m1 = x;
                c1 = 1;
            } else if(c2==0) {
                m2 = x;
                c2 = 1;
            } else {
                c1--; c2--;
            }
        }
        c1 = 0; c2 = 0;
        for(int i=0; i<nums.length; i++) {
            if(m1 == nums[i]) c1++;
            else if(m2 == nums[i]) c2++;
        }
        if(c1 > nums.length / 3) res.add(m1);
        if(c2 > nums.length / 3) res.add(m2);
        return res;
    }
}

希望這篇博文能讓大家對摩爾投票法有一個認識,對這樣類似的演算法題可以換一個角度來考慮,就會變得簡單很多,謝謝。