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.python

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

思路:數組

Find k different element, and 「remove」 them as a group, the remaining element must be the element that appears more than ⌊n/k⌋ times. (Detailed explanation is given in comment)markdown

In this problem, k equals to 2.app

Thus we 「remove」 each pair of 2 different elements, and the remaining element that do not have its counterpart is the desired element.
時間複雜度O(n)空間複雜度O(1)的算法呢? 實際上,早在91年就有人專門就這個問題發表了論文,介紹了一種線性時間的算法: Majority Vote Algorithm。經過名字就能夠看出,這個算法是專門用來解決這個問題的。而因爲做者是J Moore (目前是Utexas的計算機系主任),這個算法有時候也會被稱爲Moore’s Voting Algorithm (固然這個Moore並非提出Moore’s Law的那個Gordon Moore)。ui

算法的基本思想很是簡潔: 每次都找出一對不一樣的元素,從數組中刪掉,直到數組爲空或只有一種元素。 不難證實,若是存在元素e出現頻率超過半數,那麼數組中最後剩下的就只有e。固然,最後剩下的元素也可能並無出現半數以上。好比說數組是[1, 2, 3],最後剩下的3顯然只出現了1次,並不到半數。排除這種false positive狀況的方法也很簡單,只要保存下原始數組,最後掃描一遍驗證一下就能夠了。this

如今來分析一下複雜度。刪除元素能夠在常數時間內完成,但找不一樣元素彷佛有點麻煩。實際上,咱們能夠換個角度來想,用一個小trick來從新實現下該算法。spa

在算法執行過程當中,咱們使用常量空間實時記錄一個候選元素c以及其出現次數f(c),c即爲當前階段出現次數超過半數的元素。在遍歷開始以前,該元素c爲空,f(c)=0。而後在遍歷數組A時,.net

若是f(c)爲0,表示當前並無候選元素,也就是說以前的遍歷過程當中並無找到超過半數的元素。那麼,若是超過半數的元素c存在,那麼c在剩下的子數組中,出現次數也必定超過半數。所以咱們能夠將原始問題轉化爲它的子問題。此時c賦值爲當前元素, 同時f(c)=1。
若是當前元素A[i] == c, 那麼f(c) += 1。(沒有找到不一樣元素,只須要把相同元素累計起來)
若是當前元素A[i] != c,那麼f(c) -= 1 (至關於刪除1個c),不對A[i]作任何處理(至關於刪除A[i])

若是遍歷結束以後,f(c)不爲0,那麼再次遍歷一遍數組,記錄c真正出現的頻率,從而驗證c是否真的出現了超過半數。上述算法的時間複雜度爲O(n),而因爲並不須要真的刪除數組元素,咱們也並不須要額外的空間來保存原始數組,空間複雜度爲O(1)。實際上,在Moore大牛的主頁上有針對這個算法的一個演示,感興趣的同窗能夠直接移步觀看。code

這個問題看上去已經完美的解決了。

2、更通常的狀況呢?

那麼,若是咱們想找的並非超過半數的元素,而是出現頻率超過必定頻率的元素都要找出來,是否也存在一個相似的線性時間的算法呢?答案是確定的。實際上,這一類從特定的數據集中找出出現頻率超過某個閾值的元素的問題,有一個形象的名字叫作Iceberg query,或者叫作host list分析。而Richard Karp 老爺子當年就專門寫了一篇論文來討論這種通常性問題的解決方案,而經過下文的介紹,你們也能夠發現,Karp的方案應該也是受到了Moore的算法的啓發。

首先仍是看一下問題的形式化定義吧:

對於一個序列 以及一個在(0,1)之間的實數。假定表示元素的出現頻率,咱們須要找到全部知足的元素。

原帖鏈接:
https://leetcode.com/discuss/19151/solution-computation-space-problem-can-extended-situation

http://m.blog.csdn.net/blog/wenyusuran/40780253

解決方案:

class Solution {
public:
    int majorityElement(vector<int>& nums)
    {
        int size = nums.size();
        int vote = 0;
        int count = 0;

        for(int i = 0;i < size;i++)
        {
            if(count == 0)
            {
                vote = nums[i];
                count = 1;
            }
            else
            {
                if(vote == nums[i])
                count++;
                else
                count--;
            }
        }
        return vote;
    }
};

STL解決方案:

int majorityElement(vector<int> &num)
 {
        map<int, int>count;
        for (vector<int>::iterator i = num.begin(); i != num.end();i++) 
        {
            if ( (++count[*i]) > num.size() / 2)
                return *i;

        }
    }

c語言:

int majorityElement(int num[], int n)
 {
    int cnt = 0, res;
    for (int i = 0; i < n; ++i) 
    {
        if (cnt == 0) res = num[i];
        if (res == num[i]) ++cnt;
        else --cnt;
    }
    return res;
}

python解決方案:

class Solution:
        # @param {integer[]} nums
        # @return {integer}
        def majorityElement(self, nums):
            count = {}
            for i in nums:
                if i not in count:
                    count[i] = 0
                count[i] += 1
                if count[i] > len(nums)/2:
                    return i
相關文章
相關標籤/搜索