day13 代码随想录算法训练营 347. 前 K 个高频元素 【待梳理】

发布时间 2024-01-09 18:07:29作者: o蹲蹲o

题目:347. 前 K 个高频元素

我的感悟:

  • 我用hash再排序。
  • 卡尔用的小顶堆。
`heapq`是Python中的一个模块,它提供了堆队列(也称优先队列或者堆)的算法实现。在计算机科学中,堆是一种特殊的完全二叉树数据结构,其中每个父节点的值都小于或等于其子节点的值(在最小堆中)或者父节点的值都大于或等于其子节点的值(在最大堆中)。`heapq`模块实现了最小堆排序算法。

`heapq`模块中最常用的函数包括:

- `heapify(iterable)`: 将可迭代对象转化为堆数据结构。
- `heappush(heap, elem)`: 将元素`elem`添加到堆`heap`中,并保持堆的性质。
- `heappop(heap)`: 弹出并返回`heap`中最小的元素,保持堆的性质。
- `heappushpop(heap, elem)`: 将元素`elem`压入堆中,然后弹出并返回`heap`中最小的元素。
- `heapreplace(heap, elem)`: 弹出并返回`heap`中最小的元素,然后将新元素`elem`压入堆中。

以下是一些使用`heapq`模块的例子:

```python
import heapq

# 创建一个空的堆
heap = []

# 将一些元素添加到堆中
heapq.heappush(heap, 3)
heapq.heappush(heap, 1)
heapq.heappush(heap, 2)
heapq.heappush(heap, 4)

# 从堆中弹出最小的元素
print(heapq.heappop(heap))  # 输出 1

# 查看堆中的元素
print(heap)  # 输出 [2, 4, 3]

# 将一个列表转换为一个堆
nums = [5, 7, 9, 1, 3]
heapq.heapify(nums)
print(nums)  # 堆化后的列表,例如输出 [1, 3, 9, 7, 5]

# 弹出最小元素,然后将新元素压入堆中
print(heapq.heappushpop(nums, 4))  # 输出 1,nums 变为 [3, 4, 9, 7, 5]
```

除了上面列出的函数,`heapq`模块还提供了`nlargest(n, iterable)`和`nsmallest(n, iterable)`等函数来获取可迭代对象中的n个最大或最小元素。

需要注意的是,`heapq`模块只提供了最小堆的实现。如果你需要最大堆的功能,可以通过插入元素的相反数来间接实现,或者自定义比较函数,使用`heapq`处里元素的时以(-element, element)这种元组形式来保持最大堆的属性。

 

理解难点:

代码难点:

代码示例:

#时间复杂度:O(nlogk)
#空间复杂度:O(n)
import heapq
class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        #要统计元素出现频率
        map_ = {} #nums[i]:对应出现的次数
        for i in range(len(nums)):
            map_[nums[i]] = map_.get(nums[i], 0) + 1
        
        #对频率排序
        #定义一个小顶堆,大小为k
        pri_que = [] #小顶堆
        
        #用固定大小为k的小顶堆,扫描所有频率的数值
        for key, freq in map_.items():
            heapq.heappush(pri_que, (freq, key))
            if len(pri_que) > k: #如果堆的大小大于了K,则队列弹出,保证堆的大小一直为k
                heapq.heappop(pri_que)
        
        #找出前K个高频元素,因为小顶堆先弹出的是最小的,所以倒序来输出到数组
        result = [0] * k
        for i in range(k-1, -1, -1):
            result[i] = heapq.heappop(pri_que)[1]
        return result

通过截图:

扩展写法:

from collections import Counter
class Solution:
    def topKFrequent(self, nums: list[int], k: int) -> list[int]:
        res = []
        new_nums = Counter(nums)
        sorted_nums = sorted(new_nums.items(), key=lambda x: x[1], reverse=True)
        #注意这里的items()返回的是一个元组,上下文的下标操作是对元组进行的,不是对字典操作的
        for i in range(k):
            res.append(sorted_nums[i][0])
        return res

资料: