239. 滑动窗口最大值
暴力解法超时了
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
result = []
_list = []
i = 0
while i < len(nums):
if i < k:
_list.append(nums[i])
i += 1
else:
result.append(max(_list))
_list = _list[1:]
_list.append(nums[i])
i += 1
result.append(max(_list))
return result
利用python双端队列 deque()来构造单调队列ddque()
from collections import deque
class ddeque():
def __init__(self):
self._list = deque()
def pop_left_(self , val):
if self._list[0] == val:
self._list.popleft()
def push_right_(self, val):
while self._list and self._list[-1] < val:
self._list.pop()
self._list.append(val)
def get_max_(self):
return self._list[0]
def print(self):
return self._list
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
result = []
_list = ddeque()
i = 0
while i < len(nums):
if i < k:
_list.push_right_(nums[i])
i += 1
else:
result.append(_list.get_max_())
_list.pop_left_(nums[i - k])
_list.push_right_(nums[i])
i += 1
result.append(_list.get_max_())
return result
基本思想是
左端pop_left(val) 如果窗口中需要左出的值和单调队列中最左端的值(默认是最大值,因为是单调队列)相等 那么就再单调队列中pop_left() 否则不做操作,这样保证了单调队列最左端的值就一直是滑动窗口中的最大值。
右端push_right_(val): 如果窗口中需要右进的值比单调队列中最右端的值大,那么就单调队列最右端的值右出一个,就是pop() "pop()默认是出右端",那么直到找到单调队列中最右端的值比需要右进的值大,则把这个值加入单调队列
这两个操作保证了 1. 单调队列中最左端的值就是滑动窗口的最大值 2. 队列是单调递减的
所以如果滑动窗口中的最大值要出去了,单调队列中的最大值也对应左出,那么第二大的值就候补上来。由于右端push_right_的操作,可以保证单调队列中是按最大值,第二大,第三大的顺序排列,从而不会遗漏最大值。
另外对于python deque()的双端队列:
1. .append(): 右添加元素
2. .appendleft():左添加元素
3. .pop(): 右弹出元素并返回右端元素
4. .popleft(): 左弹出元素并返回左端元素
5. .reverse(): 原地反转
6. .insert(i,x): 在位置i插入x
7. .count(x): 计算deque中元素x出现的次数
8. .clear(): 清空
9. .remove(): 移除找到的第一个元素
347. 前K个高频元素
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
dic = {}
result = []
for i in nums:
if i not in dic:
dic[i] = 1
else:
dic[i] += 1
sorted_dic = sorted(dic.items(), key = lambda item: item[1], reverse = True)
i = 0
for key,val in sorted_dic:
result.append(key)
i += 1
if i >= k:
break
return result
利用哈希表的思想 统计每个数字出现的频率,然后对字典排序,降序排列之后输出前k个的键