📜  门| GATE-CS-2002 |问题5(1)

📅  最后修改于: 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。遍历数组中的元素,如果当前元素等于candidatecount加一;否则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)$。