1. 程式人生 > 其它 >第92期-基礎技巧:計數 多數元素

第92期-基礎技巧:計數 多數元素

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]:
        #在此之間填寫程式碼
print(Solution().majorityElement([3,2,3])) print(Solution().majorityElement([1])) print(Solution().majorityElement([1,1,1,3,3,2,2,2]))
View Code

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
                cnt1
+=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]))
View Code

第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行:返回最後兩個列表相加形成的列表

程式碼執行結果為:

#技巧講解

這裡用到了基礎技巧:計數:摩爾投票法,簡單講解下這個技巧:
摩爾投票法
摩爾投票法的基本思想很簡單,在每一輪投票過程中,從陣列中找出一對不同的元素,將其從陣列中刪除。
這樣不斷的刪除直到無法再進行投票,如果陣列為空,則沒有任何元素出現的次數超過該陣列長度的一半。
如果只存在一種元素,那麼這個元素則可能為目標元素。


那麼有沒有可能出現最後有兩種或兩種以上元素呢?
根據定義,這是不可能的,因為如果出現這種情況,則代表我們可以繼續一輪投票。
因此,最終只能是剩下零個或一個元素