陣列中出現次數超過一半的數字~
阿新 • • 發佈:2021-10-13
讀前福利
問題描述
給一個長度為 n 的陣列,陣列中有一個數字出現的次數超過陣列長度的一半,請找出這個數字。例如輸入一個長度為9的陣列[1,2,3,2,2,2,5,4,2]。由於數字2在陣列中出現了5次,超過陣列長度的一半,因此輸出2。
示例:
輸入:[1,2,3,2,2,2,5,4,2]
輸出:2
分析問題
雜湊表法
我們最容易想到的方法就是使用雜湊表法,去統計每個數字出現的次數,即可很容易的求出眾數。
def majorityElement(nums): #用字典來儲存每個數字出現的次數 data_count = {} for x in nums: if x in data_count: data_count[x] = data_count[x] + 1 else: data_count[x] = 1 max_value=0 max_key=0 #遍歷字典,取出次數最大的 #因為題目說給定的陣列一定存在眾數 #所以最大的次數就是眾數 for key in data_count: value=data_count[key] if value>max_value: max_value=value max_key=key return max_key data=[1,2,3,2,2,2,5,4,2] print(majorityElement(data))
該演算法的時間複雜度是O(n),空間複雜度也是O(n)。
排序演算法
我們將陣列進行排序,那排序後的陣列的中點一定就是眾數。
def majorityElement(nums):
#將陣列排序
nums.sort()
#返回排序陣列中的中點
return nums[len(nums) // 2]
data=[1,2,3,2,2,2,5,4,2]
print(majorityElement(data))
Boyer-Moore 投票演算法
這道題最經典的解法是Boyer-Moore 投票演算法。Boyer-Moore 投票演算法的核心思想是票數正負抵消,即遇到眾數時,我們把票數+1,遇到非眾數時,我們把票數-1,則所有的票數和一定是大於0的。
我們假設陣列nums的眾數是x,陣列的長度為n。我們可以很容易的知道,若陣列的前a個數字的票數和為0,那麼剩餘n-a個數字的票數和一定是大於0的,即後n-a個數字的眾數仍然為x。
我們記陣列的首個元素是n1,陣列的眾數是x,遍歷並統計票數。當發生票數和為0時,陣列剩餘元素的眾數一定也是x,這是因為:
- 當n1等於x時,抵消的所有數字中,有一半是眾數x。
- 當n1不等於x時,抵消的所有數字中,眾數的個人最少為0,最多為一半。
所以,我們在去掉m個字元裡,最多隻去掉了一半的眾數,所以在剩餘的n-m個元素中,x仍然為眾數。利用這個特性,在每次遇到票數和為0時,我們都可以縮小剩餘陣列區間。當遍歷完成時,最後一輪假設的數字即為眾數。
class Solution:
def majorityElement(self, nums):
#票數和
counts=0
for num in nums:
#如果票數和為0,我們假設num元素為眾數
if counts == 0:
x = num
#如果是眾數票數+1,否則票數-1
if num==x:
counts=counts+1
else:
counts=counts-1
return x
該演算法的時間複雜度是O(n),空間複雜度是O(1)。
最後
送大家幾本比較不錯的演算法書籍~
小爭哥資料結構與演算法
連結:https://pan.baidu.com/s/19Jk_G_-QTnGb3GRyzbENgA
密碼:keis
谷歌大佬LeetCode刷題指南
連結:https://pan.baidu.com/s/1vtRIsVltTxmIioqqkeSS5g
密碼:r3xg
演算法小抄
連結:https://pan.baidu.com/s/1rU_T6GRZ-WmV9QFmnJfCBg
密碼:unh5
更多有趣內容,請掃碼關注一波~