📜  门| GATE 2017 MOCK II |第 59 题(1)

📅  最后修改于: 2023-12-03 15:12:34.992000             🧑  作者: Mango

题目介绍

本题为 GATE 2017 MOCK II 的第 59 题,考察了程序员对于算法的理解与实现能力。

问题描述

给定一个整数数组 arr 和一个整数 k,请你找出数组中的 top k 大元素并返回它们的下标。若有多个元素出现频率相同,则返回下标较小的元素。你可以假定 k 总是小于等于传入数组的长度。

函数原型为:

def top_k(arr: List[int], k: int) -> List[int]:
    pass
示例
arr = [1, 1, 1, 2, 2, 3]
k = 2
assert top_k(arr, k) == [3, 4]

arr = [1, 1, 2, 2, 3]
k = 1
assert top_k(arr, k) == [2]

arr = [1, 2, 2, 3, 3, 3]
k = 2
assert top_k(arr, k) == [3, 4]
算法思路
解法一:哈希表 + 排序

首先我们可以统计数组中每个元素出现的次数,对出现次数进行排序,并返回前 k 个元素的下标。需要注意的是,若有多个元素出现的次数相同,则返回下标较小的元素。

解法二:堆

对于 top k 问题,我们可以使用堆来解决。具体步骤如下:

  1. 维护一个最小堆,初始为空。
  2. 遍历数组中每个元素,将其加入到堆中。
  3. 当堆的大小超过 k 时,弹出堆顶元素。
  4. 遍历数组完毕后,堆中剩下的 k 个元素即为所求。

需要注意的是,此处我们维护的是最小堆,因此堆顶元素为数组中的最小值。

代码实现
解法一:哈希表 + 排序
from typing import List


def top_k(arr: List[int], k: int) -> List[int]:
    freq = {}
    for i, num in enumerate(arr):
        freq[num] = freq.get(num, 0) + 1

    items = list(freq.items())
    items.sort(key=lambda x: (-x[1], x[0]))

    res = []
    for i in range(k):
        res.append(items[i][0])
    res.sort()

    return [arr.index(num) for num in res]
解法二:堆
import heapq
from typing import List


def top_k(arr: List[int], k: int) -> List[int]:
    heap = []
    for i, num in enumerate(arr):
        heapq.heappush(heap, (num, i))
        if len(heap) > k:
            heapq.heappop(heap)

    res = []
    while heap:
        res.append(heapq.heappop(heap)[1])
    res.reverse()

    return res
总结

本题考察了程序员对于算法的理解与实现能力,需要掌握哈希表和优先队列(如堆)的使用,以及对算法复杂度的分析。在解决 top k 问题时尤其需要注意。