【堆】No. 0347 前k个高频元素【中等】👉力扣对应题目指路

希望对你有帮助呀!!💜💜 如有更好理解的思路,欢迎大家留言补充 ~ 一起加油叭 💦
欢迎关注、订阅专栏 【力扣详解】谢谢你的支持!
⭐ 题目描述:给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素
-
你可以按 任意顺序 返回答案,要求复杂度 必须 优于 O(NlogN)
-
示例 :
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
🔥 思路:首先遍历整个数组,并使用哈希表
num_hash
记录每个数字出现的次数。找出原数组的前 k 个高频元素,就相当于找出出现的次数的前 k 大值对应的数组元素。
- 最简单的做法是给按照
num_hash
排序,但是复杂度为O(NlogN)
不满足优于 O(NlogN)- 利用堆的思想:## 维护一个
k 个
元素的小根堆
- 不熟悉堆的友友 👉 【概念速通】堆 什么是堆,如何建堆,堆能干嘛

具体步骤如下:
- 步骤一:遍历整个数组,并使用哈希表
num_hash
记录每个数字出现的次数- 步骤二:创建堆
num_heap
及编写对应的上滤heap_up
下滤heap_down
函数
- 上滤、下滤具体怎么操作 👉 【概念速通】堆 什么是堆,如何建堆,堆能干嘛
- 步骤三:对于
num_hash
中的每个元素
- 情况一:堆的元素个数小于 k,插入
num_heap
- 情况二:堆的元素个数等于 k,检查堆顶与当前出现次数
- 堆顶更大:继续,不插入
- 当前出现次数更大:弹出堆顶,并将当前值插入堆中
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
# ------------------------------------ step 1
num_hash = {}
for num in nums:
if num in num_hash.keys():
num_hash[num] += 1
else:
num_hash[num] = 1
# ------------------------------------ step 2
num_heap = []
def heap_up():
cur = len(num_heap) - 1 ## 最后一个元素
while cur:
parent_idx = (cur-1) // 2 ## 父节点获取
if num_hash[num_heap[cur]] < num_hash[num_heap[parent_idx]]: ## 判断是否上滤
## 上滤
num_heap[cur], num_heap[parent_idx] = num_heap[parent_idx], num_heap[cur]
cur = parent_idx
else:
break
def heap_down():
cur = 0 ## 根元素
while 2*cur + 1 < len(num_heap):
## 目标子节点 (左右子节点中更大的那个) 获取
c1 = 2*cur + 1
c2 = 2*cur + 2
c = c1 if c2 >= len(num_heap) or num_hash[num_heap[c1]]<num_hash[num_heap[c2]] else c2
if num_hash[num_heap[cur]] > num_hash[num_heap[c]]: ## 判断是否下滤
## 下滤
num_heap[cur], num_heap[c] = num_heap[c], num_heap[cur]
cur = c
else:
break
# ------------------------------------ step 3
for i in num_hash.keys():
if len(num_heap) < k: # ------- step 3.1
num_heap.append(i)
heap_up()
else: # ----------------------- step 3.2
if num_hash[i] <= num_hash[num_heap[0]]: # 如果比根元素小,继续,不插入
continue
else: # 否则,弹出弹元素,插入
num_heap.append(i)
num_heap[0] = num_heap.pop()
heap_down()
return num_heap
希望对你有帮助呀!!💜💜 如有更好理解的思路,欢迎大家留言补充 ~ 一起加油叭 💦
🔥 LeetCode 热题 HOT 100