1. 程式人生 > >【演算法分析與設計】【第五週】169. Majority Element

【演算法分析與設計】【第五週】169. Majority Element

方法概覽

這題和《演算法概論習題》2.23是一樣的。老師剛講過,複習一下。

題目大意:找到出現次數超過一半的元素。
看到題目,應該想到,給定一個整數陣列,找出出現次數大於N/2 的那個數,且這樣的數若存在,就僅僅存在一個

方法很多,這裡總結四種。

方法 複雜度
快排 O(nlogn)
topK O(n)
分治 O(nlogn)
投票演算法 O(n)

視作中位數問題

首先要明白,如果一個元素的個數超過N/2則這個元素必然是這N個元素的中位數。則題目轉化為找中位數。

方法一(快排)

方法一:最直白的一種,用快排演算法,將該陣列排序,其中中位數就是主元素,這很容易想通。快排O(nlogn),找中位數O(1)快排演算法前兩週寫了多次了,本週就先不寫了。

方法二(topK)

方法二:topK也是剛剛複習過的內容,只不過這裡的K位置比較特殊,第K大是中位數而已。

分治

方法三

方法三:根據2.23的提示,先採取分治的思想,用一種複雜度在O(nlogn)的演算法。

本題最佳

方法四

方法四:多數投票演算法。

思路大致如下:
1.如果count==0,則將now的值設定為陣列的當前元素,將count賦值為1;
2.反之,如果now和現在陣列元素值相同,則count++,反之count–;
3.重複上述兩步,直到掃描完陣列。
在本題中,題目明確了主元素是存在的,簡化了一些步驟,沒有了後邊的檢查步驟。

class Solution {
public:
    vector<int> majorityElement(vector<int>& nums) {
        vector<int> v;
        int size = nums.size();
        int n1=0,n2=0,cn1=0,cn2=0;
        for(int i=0;i<size;i++)
        {
            if(nums[i]==n1)
            {
                cn1++;
            }
            else
if(nums[i]==n2) { cn2++; } else if(cn1==0) { n1 = nums[i]; cn1 = 1; } else if(cn2==0) { n2 = nums[i]; cn2 = 1; } else { cn1--; cn2--; } } if(cn2==0&&size>0)//用來解決[0 0]的情況 n2=nums[0]-1; cn1=0; cn2=0; for(int i=0;i<size;i++) { if(nums[i]==n1) cn1++; if(nums[i]==n2) cn2++; } if(cn1>size/3) v.push_back(n1); if(cn2>size/3) v.push_back(n2); return v; } };

(題目升級)找出現次數多於N/3的元素

依然是多數投票演算法 Majority Vote Algorithm,這裡講解挺詳細。