239. Sliding Window Maximum(还需再写)
1. 暴力解法O(n*k)
2. 不能用max-heap:因为这个窗口是移动的,而大顶堆每次只能弹出最大值,我们无法移除其他数值,这样就造成大顶堆维护的不是滑动窗口里面的数值了。
3. 需要一个queue,实现三个功能:que.pop(滑动窗口中移除元素的数值),que.push(滑动窗口添加元素的数值),然后que.front()就返回我们要的最大值
4. 单调队列:其实队列没有必要维护窗口里的所有元素,只需要维护有可能成为窗口里最大值的元素就可以了,同时保证队列里的元素数值是由大到小的。那么这个维护元素单调递减的队列就叫做单调队列,即单调递减或单调递增的队列。
5. 设计单调队列的时候,pop,和push操作要保持如下规则:
- pop(value):如果窗口移除的元素value等于单调队列的出口元素,那么队列弹出元素,否则不用任何操作
- push(value):如果push的元素value大于入口(右侧)元素的数值,那么就将队列入口的元素弹出,直到push元素的数值小于等于队列入口元素的数值为止【因为从左到右单调递减,而且push进来的数又大又long-live】
保持如上规则,每次窗口移动的时候,只要问que.front()就可以返回当前窗口的最大值。
6. time complexity:O(n)
nums 中的每个元素最多也就被 push_back 和 pop_back 各一次,没有任何多余操作,所以整体的复杂度还是 O(n)
7. 用deque:常用的queue在没有指定容器的情况下,deque就是默认底层容器,直接用list会超时(list.pop()时间复杂度为O(n),这里需要使用collections.deque())
from collections import deque
class MyQueue:
def __init__(self):
self.queue = deque()
def pop(self,value):
if self.queue and value == self.queue[0]: #先确定queue不为空 #和出口处(左边)元素比较 queue[0]
self.queue.popleft()
def push(self,value):
while self.queue and value>self.queue[-1]:
self.queue.pop() #popright
self.queue.append(value)
def front(self):
return self.queue[0]
class Solution(object):
def maxSlidingWindow(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: List[int]
"""
que = MyQueue()
result =[]
for i in range(k):
que.push(nums[i])
result.append(que.front())
for i in range(k,len(nums)):
que.pop(nums[i-k])
que.push(nums[i])
result.append(que.front())
return result
347. Top K Frequent Elements(还需再写)
quicksort O(nlogn),所以算法的时间复杂度必须优于此
大顶堆,小顶堆->很大数据集里求前k个高频/低频元素
时间复杂度nlogk ->k个元素的树
此题
- 要统计元素出现频率: map
- 对频率排序: priority queue
- priority queue就是一个披着队列外衣的堆,
因为优先级队列对外接口只是从队头取元素,从队尾添加元素,再无其他取元素的方式,看起来就是一个队列。而且优先级队列内部元素是自动依照元素的权值排列
-
大家经常说的大顶堆(堆头是最大元素),小顶堆(堆头是最小元素),如果懒得自己实现的话,就直接用priority_queue(优先级队列)就可以了,底层实现都是一样的
3. 找出前K个高频元素
-
我们要用小顶堆,因为要统计最大前k个元素,只有小顶堆每次将最小的元素弹出,最后小顶堆里积累的才是前k个最大元素。
具体操作:
import heapq
heappush
heappop ->pop最小值,min-heap,留下的都是大的
import heapq class Solution(object): def topKFrequent(self, nums, k): """ :type nums: List[int] :type k: int :rtype: List[int] """ from collections import defaultdict dic = defaultdict(int) for i in range(len(nums)): dic[nums[i]]+=1 pri_que = [] #min-heap for key,freq in dic.items(): heapq.heappush(pri_que,(freq,key)) if len(pri_que)>k: #维持min-heap只有k个元素,heappop最小值 heapq.heappop(pri_que) #如果要从大到小排,要倒叙输出: result = [0]*k for i in range(k-1,-1,-1): result[i] = heapq.heappop(pri_que)[1] return result