239. 滑动窗口最大值
所以deque是双向都可以pop的吗。 单调队列,每次做都觉得比较难想,不知道怎么根据题目设计单调队列或单调栈。 本题:需要的是最大值,因此每次输出的时候是最大值,直到这个最大值被pop出去,后面一个最大值顶上。因此是一个递减的单调队列。为了维持递减这个属性,每次append的时候,需要比较队尾元素和append的数,小于value的就popright,然后append进去。 一个问题:为什么front的时候单调队列里一直有数。因为每次front前都有一个append,因此一定会有数。 时间复杂度O(n),空间复杂度O(k)
from collections import deque
class queue ( ) :
def __init__ ( self) :
self. q = deque( )
def pop ( self, value) :
if self. q and self. q[ 0 ] == value:
self. q. popleft( )
def append ( self, value) :
while self. q and value > self. q[ - 1 ] :
self. q. pop( )
self. q. append( value)
def front ( self) :
return self. q[ 0 ]
class Solution :
def maxSlidingWindow ( self, nums: List[ int ] , k: int ) - > List[ int ] :
q = queue( )
result = [ ]
for i in range ( k) :
q. append( nums[ i] )
result. append( q. front( ) )
for i in range ( k, len ( nums) ) :
q. pop( nums[ i- k] )
q. append( nums[ i] )
result. append( q. front( ) )
return result
stack = [ ]
for i in range ( k) :
stack. append( nums[ i] )
output = [ ]
max_ = max ( stack)
output. append( max_)
for i in range ( k, len ( nums) ) :
stack. pop( 0 )
stack. append( nums[ i] )
if nums[ i] > max_:
max_ = nums[ i]
else :
max_ = max ( stack)
output. append( max_)
return output
347. 前k个高频元素
所以heapq是可以直接用的?heapq.heappush是堆的push,heapq.heappop是堆的pop。那怎么确定是大顶堆还是小顶堆的? 时间复杂度O(nlogk),空间复杂度O(n) heap可以是一个元组(freq,key)?
class Solution :
def topKFrequent ( self, nums: List[ int ] , k: int ) - > List[ int ] :
counter = Counter( nums)
pri_que = [ ]
for key, freq in counter. items( ) :
heapq. heappush( pri_que, ( freq, key) )
if len ( pri_que) > k:
heapq. heappop( pri_que)
result = [ 0 ] * k
for i in range ( k- 1 , - 1 , - 1 ) :
result[ i] = heapq. heappop( pri_que) [ 1 ]
return result
总结
单调栈/单调队列迷迷糊糊的 堆/优先级队列也迷迷糊糊的 以前应该是学过的,大顶堆小顶堆二叉树什么的,难过了,明天恶补一下
215. 数组中的第k个最大元素
动手写了一下大顶堆,大概就是用一个数组维护一个大顶堆的完全二叉树(不过为什么不是直接用树结构?二叉树的底层是数组?),需要写add和pop两个函数。 add的时候,加的数加在完全二叉树的末尾,然后通过上移,完成堆的维护。 pop的时候,将堆顶和堆尾进行调换顺序,然后将堆尾的节点pop掉,堆顶的节点下移,完成堆的维护。 python里可以直接用heapq库来调用堆。heapq实现的是小顶堆。因此本地需要的是第k个最大元素的话,就是维护一个k大小的优先级序列,如果输入的数大于这个小顶堆的顶,那么pop出这个最小的元素,push入新的数。
heapq.heappush(heap, item):将元素item添加到堆heap中。 heapq.heappop(heap):从堆heap中弹出并返回最小(或最大)的元素。 heapq.heapify(heap):将列表heap原地转换为一个合法的堆。 heapq.heapreplace(heap, item):将堆heap中的最小(或最大)元素弹出,并将元素- item添加到堆中。 heapq.heappushpop(heap, item):将元素item添加到堆heap中,并返回堆中的最小(或最大)元素。 heapq.nlargest(k, iterable):返回可迭代对象iterable中最大的k个元素。 heapq.nsmallest(k, iterable):返回可迭代对象iterable中最小的k个元素。
class MaxHeap ( ) :
def __init__ ( self) :
self. _data = [ ]
self. _count = 0
def size ( self) :
return self. _count
def isEmpty ( self) :
return self. _count == 0
def add ( self, x) :
self. _data. append( x)
self. _shift_up( self. _count)
self. _count += 1
def pop ( self) :
if self. _count:
ret = self. _data[ 0 ]
self. _count -= 1
self. _data[ 0 ] = self. _data[ - 1 ]
self. _data. pop( )
self. _shift_down( 0 )
return ret
def _shift_up ( self, index) :
parent = ( index - 1 ) // 2
while index > 0 and self. _data[ index] > self. _data[ parent] :
self. _data[ index] , self. _data[ parent] = self. _data[ parent] , self. _data[ index]
index = parent
parent = ( index - 1 ) // 2
def _shift_down ( self, index) :
max_child = ( index << 1 ) + 1
while max_child < self. _count:
if max_child + 1 < self. _count and self. _data[ max_child] < self. _data[ max_child+ 1 ] :
max_child += 1
if self. _data[ index] < self. _data[ max_child] :
self. _data[ index] , self. _data[ max_child] = self. _data[ max_child] , self. _data[ index]
index = max_child
max_child = ( index << 1 ) + 1
else :
break
class Solution :
def findKthLargest ( self, nums: List[ int ] , k: int ) - > int :
heap = [ ]
for i in range ( k) :
heapq. heappush( heap, nums[ i] )
for i in range ( k, len ( nums) ) :
if nums[ i] > heap[ 0 ] :
heapq. heappop( heap)
heapq. heappush( heap, nums[ i] )
return heap[ 0 ]
n = len ( nums)
heap = MaxHeap( )
for i in nums:
heap. add( i)
for i in range ( k) :
result = heap. pop( )
return result