給定一個長度爲 n
的數組:java
int[] nums
其中有一個數,它出現的次數大於n/2
,稱爲主要元素,找到它。python
看起來不算是個難題,但好玩。算法
這是一個投票問題,能夠模擬咱們在投票表決時的計票過程。用一個hash table或者dictionary,數組中的數做爲key,它們出現的次數爲value。本文想討論的是下邊這些算法。數組
結論很簡單:排序完以後,主要元素必然在下標n/2
的位置。看下面兩個例子就很清楚了:code
nums: 1, 1, 1, 2, 2 i 0 1 2 3 4 n/2 =5/2 =2 nums[2]=1 主要元素是最小的數,排序後集中在最左邊
nums: 1, 1, 2, 2, 2 i 0 1 2 3 4 n/2 =5/2 =2 nums[2]=2 主要元素是最大的數,排序後集中在最右邊
若是主要元素既不是最大的也不是最小的,那主要元素集中在中間一段,包括n/2
。Python一句搞定:排序
def majorityElement(self, nums): return sorted(nums)[len(nums)/2]
分析:元素是int型,沒有限制更小的範圍,基於比較的排序算法,最快O(nlogn)。get
這裏設int爲32位整數。咱們對這些數以二進制的形式,逐位觀察,嘗試構造出主要元素來。對32位中的每一位,若是1佔多數,則主要元素的對應位爲1,不然爲0。hash
nums: 1, 2, 3, 3, 3 Binary: 1: 0b0000....0001 2: 0b0000....0010 3: 0b0000....0011 3: 0b0000....0011 3: 0b0000....0011 major: 0b0000....0011
Java實現:it
public int majorityElement(int[] nums) { int res=0,major=nums.length/2; for (int i=31;i>=0;i--){ int pos=0; for(int n:nums) pos+=(n>>i)&1; pos=pos>major? 1:0; res|=pos<<i; } return res; }
分析:時間複雜度爲O(n),帶個係數32,實際工做起來仍是很快的。io
提出Boyer-Moore 算法的論文。
基本思想:
比較直觀的解釋:在數組中找到兩個不相同的元素並刪除它們,不斷重複此過程,直到數組中元素都相同,那麼剩下的元素就是主要元素。
思想並不複雜,可是要憑空想出這個算法來也不是件容易的事。另外,給咱們的是數組,直接在裏面刪除元素是很費時的。取而代之,能夠利用一個計數變量來實現。
def majorityElement(self, nums): count,major=0,0 for n in nums: if count==0: major=n if major==n: count+=1 else: count-=1 return major
對於上面的代碼:
先隨意肯定一個候選元素,count是候選元素的計數,當遇到一個跟候選元素不一樣的元素時,二者數量上抵消一個,count減1。一旦count變成0,就從新找一個候選元素。
當遇到一個與候選元素不一樣的元素時,就要抵消。對於候選元素和當前元素,可能存在兩種狀況:
A. 二者中有一個正好是主要元素
B. 二者都不是主要元素
對於狀況 A,抵消事後,主要元素仍是主要元素;對於狀況 B,能夠說主要的元素的地位獲得了鞏固。因此算法最終能找到主要元素。