[LeetCode] 169. Majority Element 求大多數


 

Given an array of size n, find the majority element. The majority element is the element that appears more than ⌊ n/2 ⌋ times.

You may assume that the array is non-empty and the majority element always exist in the array.

Example 1:

Input: [3,2,3]
Output: 3

Example 2:

Input: [2,2,1,1,1,2,2]
Output: 2

 

這是到求大多數的問題,有很多種解法,其中我感覺比較好的有兩種,一種是用哈希表,這種方法需要 O(n) 的時間和空間,另一種是用一種叫摩爾投票法 Moore Voting,需要 O(n) 的時間和 O(1) 的空間,比前一種方法更好。這種投票法先將第一個數字假設為過半數,然后把計數器設為1,比較下一個數和此數是否相等,若相等則計數器加一,反之減一。然后看此時計數器的值,若為零,則將下一個值設為候選過半數。以此類推直到遍歷完整個數組,當前候選過半數即為該數組的過半數。不仔細弄懂摩爾投票法的精髓的話,過一陣子還是會忘記的,首先要明確的是這個叼炸天的方法是有前提的,就是數組中一定要有過半數的存在才能使用,下面來看本算法的思路,這是一種先假設候選者,然后再進行驗證的算法。現將數組中的第一個數假設為過半數,然后進行統計其出現的次數,如果遇到同樣的數,則計數器自增1,否則計數器自減1,如果計數器減到了0,則更換下一個數字為候選者。這是一個很巧妙的設定,也是本算法的精髓所在,為啥遇到不同的要計數器減1呢,為啥減到0了又要更換候選者呢?首先是有那個強大的前提存在,一定會有一個出現超過半數的數字存在,那么如果計數器減到0了話,說明目前不是候選者數字的個數已經跟候選者的出現個數相同了,那么這個候選者已經很 weak,不一定能出現超過半數,此時選擇更換當前的候選者。那有可能你會有疑問,那萬一后面又大量的出現了之前的候選者怎么辦,不需要擔心,如果之前的候選者在后面大量出現的話,其又會重新變為候選者,直到最終驗證成為正確的過半數,佩服算法的提出者啊,代碼如下:

 

C++ 解法一:

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        int res = 0, cnt = 0;
        for (int num : nums) {
            if (cnt == 0) {res = num; ++cnt;}
            else (num == res) ? ++cnt : --cnt;
        }
        return res;
    }
};

 

Java 解法一:

public class Solution {
    public int majorityElement(int[] nums) {
        int res = 0, cnt = 0;
        for (int num : nums) {
            if (cnt == 0) {res = num; ++cnt;}
            else if (num == res) ++cnt;
            else --cnt;
        }
        return res;
    }
}

 

下面這種解法利用到了位操作 Bit Manipulation 來解,將這個大多數按位來建立,從0到31位,每次統計下數組中該位上0和1的個數,如果1多,那么將結果 res 中該位變為1,最后累加出來的 res 就是過半數了,相當贊的方法,參見代碼如下:

 

C++ 解法二:

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        int res = 0, n = nums.size();
        for (int i = 0; i < 32; ++i) {
            int ones = 0, zeros = 0;
            for (int num : nums) {
                if (ones > n / 2 || zeros > n / 2) break;
                if ((num & (1 << i)) != 0) ++ones;
                else ++zeros;
            }
            if (ones > zeros) res |= (1 << i);
        }
        return res;
    }
};

 

Java 解法二:

public class Solution {
    public int majorityElement(int[] nums) {
        int res = 0, n = nums.length;
        for (int i = 0; i < 32; ++i) {
            int ones = 0, zeros = 0;
            for (int num : nums) {
                if (ones > n / 2 || zeros > n / 2) break;
                if ((num & (1 << i)) != 0) ++ones;
                else ++zeros;
            }
            if (ones > zeros) res |= (1 << i);
        }
        return res;
    }
}

 

Github 同步地址:

https://github.com/grandyang/leetcode/issues/169

 

類似題目:

Majority Element II

 

參考資料:

https://leetcode.com/problems/majority-element/

https://leetcode.com/problems/majority-element/discuss/51613/O(n)-time-O(1)-space-fastest-solution

https://leetcode.com/problems/majority-element/discuss/51612/6-Suggested-Solutions-in-C++-with-Explanations

https://leetcode.com/problems/majority-element/discuss/51611/Java-solutions-(sorting-hashmap-moore-voting-bit-manipulation).

https://leetcode.com/problems/majority-element/discuss/51828/C++-solution-using-Moore's-voting-algorithm-O(n)-runtime-comlexity-an-no-extra-array-or-hash-table

 

LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM