LeetCode#面試題 17.10. 主要元素

csdn_yj發表於2020-12-01

LeetCode: 面試題 17.10. 主要元素

該題有以下三種解法:

方法一:HashMap

用hashmap對每一個元素出現的次數進行計數,當發現有一個元素出現的次數過半時返回該元素,若遍歷完所有元素仍未發現次數過半的元素則返回-1。

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        map<int, int> hashTable;

        for(auto num : nums) {
            hashTable[num]++;
            if(hashTable[num] > nums.size() / 2) {
                return num;
            }    
        }

        return -1;
    }
};

方法二: 排序法

先對所有的元素進行排序(目的是把數值相同的元素放一起)然後當第i個元素和第i + nums.size() / 2個元素的值相同時,就找到了主要元素。

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        if(nums.size() == 0) {
            return -1;
        }

        sort(nums.begin(), nums.end());
        for(int i = 0; (i + nums.size() / 2) < nums.size(); i++) {
            if(nums[i] == nums[i + nums.size() / 2]) {
                return nums[i];
            }
        }

        return -1;
    }
};

方法三:摩爾投票演算法(重點來了,這也正是我寫這篇部落格的原因) 

這是後來看題解發現的方法,也是第一次聽說這個演算法。

用一個例子來解釋這個演算法,假設你面前有n(n很大)張選票,每張選票上有一個候選人ID,你需要找到票數過半的候選人。

Step1:用右手拿一張選票;

Step2:若左手中無選票,將右手中的選票放到左手上;若左手中有選票,如果兩張選票上候選人ID相同,則將右手中選票放到左手上,反之將右手中的選票和左手中的一張選票丟到一邊;

Step3: 重複Step1和Step2,直到遍歷完所有選票;

Step4:若最後左手上無選票,則不存在票數過半的候選人,反之,左手上的選票就有可能是候選人;

Step5:驗證左手上的候選人選票是否過半。

因為你每次丟掉的選票都是投不同的人的,所以如果最後左手中沒有一張選票則說明票數最多的候選人最多有一半票數,即每次丟掉的兩張選票中都有一張投他的。

如果最後左手裡還有選票,那這些選票上投的人就有可能是票數過半的人我們在檢查一下選票驗證就行了。

以下程式碼中currElement就是左手中選票的候選人ID,counter是對左手中選票的計數。

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        int counter = 0;
        int currElement = 0;

        for(auto num : nums) {
            if(counter == 0) {
                currElement = num;
                counter++;
            }    
            else if(num == currElement) {
                counter++;
            }
            else {
                counter--;
            }
        }

        if(counter != 0) {
            counter = 0;
            for(auto num : nums) {
                if(num == currElement) {
                    counter++;
                    if(counter > nums.size() / 2) {
                        return currElement;
                    }
                }
            }
        }

        return -1;
    }
};

 

相關文章