239. 滑动窗口最大值
1.题目
给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。返回 滑动窗口中的最大值 。
239. 滑动窗口最大值
2.复习前
我承认是我低估了…用原始的双指针会超时,尤其是对单调递减的序列O(n*k)
思考:当最大值不在窗口内时,如何快速找到该窗口内的最大值?
3.文章讲解
单调队列:将数据依次放入队列中,并保持元素的单调性,该题需保持单调递减,则注意如何自定义pop和push
from collections import deque
class Mydeque:
def __init__(self):
# 没想到deque也有索引,为什么用deque而不用List?
# list.pop()是O(n),不方便删除pop(0)即最前面的元素,而deque.popleft()为O(1)
self.q = deque()
def push(self, value):
# 添加元素保证不大于前面的元素,不能有等号! 这样得到的队列是单调不减排列的
while self.q and value > self.q[-1]:
self.q.pop()
self.q.append(value)
def pop(self, value):
# 删除的元素要确保队列里有
if self.q and value == self.q[0]:
self.q.popleft()
def front(self):
return self.q[0]
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
mydeque = Mydeque()
for i in range(k):
mydeque.push(nums[i])
res = []
res.append(mydeque.front())
for j in range(k, len(nums)):
mydeque.pop(nums[j - k])
mydeque.push(nums[j])
res.append(mydeque.front())
return res
347. 前 K 个高频元素
1.题目
给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
347. 前 K 个高频元素
2.复习前
就用哈希表+排序肯定可以解出来,但时间复杂度并没有减少!不知道咋整…
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
d = defaultdict(int)
for u in nums:
d[u] += 1
l = sorted(d.values(), reverse=True)[:k]
res = []
for key, value in d.items():
if value in l:
res.append(key)
return res
3.文章讲解
虽然题解里出现了快速排序的方法去减少复杂度,但个人觉得堆更适合解这类排序问题
1)利用小顶堆把k个元素中最小的元素pop出去,这样最后留下的k个元素一定就是前k个最大的,求最小的同理!
2)python中的heapq模块来实现
heapq模块详解,同时可以通过自定义优先级来实现堆内排序
3)该题时间复杂度是多少呢?
(堆的push方法应该是lgk(如果是二叉堆)
该题和求前k个最大元素方法同理
import heapq as h
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
# 用堆方法来实现
d = defaultdict(int)
res = []
for u in nums:
d[u] += 1
for key, value in d.items():
h.heappush(res, (value, key))
if len(res) > k:
h.heappop(res)
res_final = []
for cnt, value in res:
res_final.append(value)
return res_final
栈和队列总结
1.栈的应用场景:对称匹配+找和前一元素的关系
2.队列:单调队列和优先级队列(堆)的应用
文章总结
3.队列、单调队列和优先队列的比较讲解链接
4.优先队列在python里的实现实现方法