第92期-基礎技巧:計數 多數元素
阿新 • • 發佈:2022-01-06
1 問題描述
給定一個大小為n的整數陣列,找出其中所有出現超過⌊ n/3 ⌋次的元素。
進階:嘗試設計時間複雜度為 O(n)、空間複雜度為 O(1)的演算法解決此問題。
示例 1:
輸入:[3,2,3]
輸出:3
示例 2:
輸入:nums = [1]
輸出:1
示例 2:
輸入:[1,1,1,3,3,2,2,2]
輸出:[1,2]
初始程式碼
from typing import List class Solution: def majorityElement(self, nums: List[int]) -> List[int]: #在此之間填寫程式碼View Codeprint(Solution().majorityElement([3,2,3])) print(Solution().majorityElement([1])) print(Solution().majorityElement([1,1,1,3,3,2,2,2]))
2 解題思路
- 標籤:計數
- 思路:摩爾投票法
- 也可以使用雜湊表統計,但是這種方式空間複雜度較高。摩爾投票法空間複雜度較低。
- 摩爾投票法的思路:定義兩個數字兩個count,新元素是其中任意一個數字,則對應的count加一
- 若不等於兩者中的任意一個,則兩個count都減一
- 最終判斷出現次數是否大於1/3
# 3 解題方法
from typing import List class Solution: def majorityElement(self, nums: List[int]) -> List[int]: if len(nums)<3: return list(set(nums)) n1, cnt1, n2, cnt2 = 0, 0, 0, 0 for n in nums: if (cnt1==0 or n==n1) and n!=n2: n1 = n cnt1View Code+=1 continue if cnt2==0 or n==n2: n2 = n cnt2+=1 continue cnt1 -= 1 cnt2 -= 1 ans1 = [n1] if(len([i for i in nums if i==n1]) > len(nums)//3) else [] ans2 = [n2] if(len([i for i in nums if i==n2]) > len(nums)//3) else [] return list(set(ans1 + ans2)) print(Solution().majorityElement([3,2,3])) print(Solution().majorityElement([1])) print(Solution().majorityElement([1,1,1,3,3,2,2,2]))
第1-3,22-24行:題目中已經給出的資訊,執行程式碼時要根據這些程式碼進行編輯
第4行:特殊情況,當nums長度小於三時,直接返回其沒有重複值的新列表
第5行:定義變數n1,cnt1,n2,cnt2並全部賦值為0
第6行:使用for迴圈變數nums中的所有元素
第7-10行:若cnt1等於0或n1和遍歷到的值相等,且不等於n2時,令cnt1加一,結束本次迴圈
第11-14行:若cnt2等於0或n2和遍歷到的值相等、時,令cnt2加一,結束本次迴圈
第15-16行:若便利到的值與兩者都不相等,則cnt1和cnt2都減一
第17-18行:判斷最後得到的兩個數在nums中出現次數是否超過1/3,若是,則將該數放進列表中,若不是,則列表為空
第19行:返回最後兩個列表相加形成的列表
程式碼執行結果為:
#技巧講解
這裡用到了基礎技巧:計數:摩爾投票法,簡單講解下這個技巧:
摩爾投票法
摩爾投票法的基本思想很簡單,在每一輪投票過程中,從陣列中找出一對不同的元素,將其從陣列中刪除。
這樣不斷的刪除直到無法再進行投票,如果陣列為空,則沒有任何元素出現的次數超過該陣列長度的一半。
如果只存在一種元素,那麼這個元素則可能為目標元素。
那麼有沒有可能出現最後有兩種或兩種以上元素呢?
根據定義,這是不可能的,因為如果出現這種情況,則代表我們可以繼續一輪投票。
因此,最終只能是剩下零個或一個元素