📅  最后修改于: 2023-12-03 15:12:39.996000             🧑  作者: Mango
给定一个数组arr
和一个整数k
,你需要找到数组中出现次数大于n/k
的元素并返回它们。假设数组中总共有n
个元素。
def get_majority_elements(arr: List[int], k: int) -> List[int]:
pass
输入:
arr = [3, 2, 3]
k = 3
输出:
[3]
输入:
arr = [1,1,1,1,2,2,3,3,4,4,4,4]
k = 4
输出:
[1, 4]
本题可以使用Boyer-Moore投票算法求出出现次数大于n/k
的元素。
算法的基本思想是设置一个计数器count
和一个备选答案candidate
。遍历数组中的元素,如果当前元素等于candidate
,count
加一;否则count
减一。当count
变为0时,将下一个元素设置为candidate
。最终剩下的candidate
就是出现次数大于n/k
的元素。
但是本题不只有一个出现次数大于n/k
的元素。因此,需要在第一遍遍历结束后再次遍历数组,统计candidate
出现的次数,看是否满足条件。
最后,将所有出现次数大于n/k
的元素返回即可。
from typing import List
def get_majority_elements(arr: List[int], k: int) -> List[int]:
n = len(arr)
cnts = {}
# 第一次遍历
for i in range(n):
if arr[i] not in cnts:
cnts[arr[i]] = 1
else:
cnts[arr[i]] += 1
candidates = []
for key, val in cnts.items():
if val > n // k:
candidates.append(key)
res = []
# 第二次遍历
for candidate in candidates:
cnt = 0
for i in range(n):
if arr[i] == candidate:
cnt += 1
if cnt > n // k:
res.append(candidate)
return res
时间复杂度:$O(n)$
第一次遍历的时间复杂度为$O(n)$,第二次遍历的时间复杂度为$n \times O(n) = O(n^2)$,但是实际上第二次遍历只需要遍历出现次数大于n/k
的元素,因此第二次遍历的时间复杂度为$O(k)$。因此总的时间复杂度为$O(n+k)$,其中$k$是不同的元素的个数,可以认为它远小于$n$。
空间复杂度:$O(k)$
使用了一个字典存储元素出现的次数,空间复杂度为$O(k)$。