代码随想录算法训练营|239. 滑动窗口最大值; 347.前 K 个高频元素
239. 滑动窗口最大值
题目链接: 239. 滑动窗口最大值
文档讲解: 代码随想录
题目难度:中等
思路:用单调队列实现,只需要遍历一遍,重点在于利用底层deque构造单调队列
时间复杂度:O(n);空间复杂度:O(k)
下面展示 代码
:
from collections import deque
# 使用deque实现queue底层设计
class MyQueue:
# 这里需要使用deque实现单调队列,直接使用list会超时
# 单调队列:只能队尾插入,但是能两端删除且队内元素单调递增或递减(适用于求解最值问题)插入和删除的时间复杂度均为o(1)
# 单调队列功能:询问、插入和删除
def __init__(self) -> None:
self.que = deque()
# 删除
def pop(self, value):
if self.que and self.que[0] == value:
self.que.popleft() # 队首删除,若list.pop() 复杂度为o(n)
# 插入
# 保持队列单调递减
def push(self, value):
while self.que and value > self.que[-1]:
self.que.pop()
self.que.append(value)
# 查询
def front(self):
return self.que[0]
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
que = MyQueue()
res = []
for i in range(k):
que.push(nums[i])
res.append(que.front())
for j in range(k, len(nums)):
# 窗口后移
que.pop(nums[j-k])
que.push(nums[j])
res.append(que.front())
return res
347.前 K 个高频元素
题目链接: 347.前 K 个高频元素
文档讲解: 代码随想录
题目难度:中等
思路:基于小顶堆实现。小顶堆利用headq实现,之前使用headq.headpush(),若要实现大顶堆,则所有元素加负号再使用headq.headpush()。
时间复杂度:O(nlogk);空间复杂度:O(k)
代码
如下
#时间复杂度:O(nlogk)
#空间复杂度:O(n)
# 基于小顶堆实现
import heapq
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
# 1、统计各元素的频率
map1 = {}
for i in range(len(nums)):
# 没有nums[i]的键,则输出默认的值0
map1[nums[i]] = map1.get(nums[i], 0) + 1
# 2、定义小顶堆(heapq实现,大小为k)
pri_que = []
for key, freq in map1.items():
# 小顶堆先弹出最小元素
heapq.heappush(pri_que, (freq, key))
if len(pri_que) > k:
heapq.heappop(pri_que)
# 3、取最后留在顶栈的元素(倒序输出)
res = [0] * k
for j in range(k-1, -1,-1):
# heapq.heappop(pri_que)为(freq, key),因此要加[1]
res[j] = heapq.heappop(pri_que)[1]
return res