day12|栈和队列

  1. 滑动窗口最大值(单调队列):仅维护当前队列的最大值
    from collections import deque
  2. 前k个最大的元素(优先级队列)
    import heapq

239. 滑动窗口最大值

思路: 可以考虑使用暴力法进行求解,滑动窗口,自定义单调队列利用O(1)的时间复杂度求解题目的结果。
反思:

  1. 巧妙的解题思路,仅维护每个序列中最大的数值即可。
  2. 在每一次弹出时,如果队首是这个元素那么进行弹出,如果不是这个元素就不用进行弹出了。
  3. 需要自定义一个升序队列。
from collections import deque
# collections中的deque
#list.pop()时间复杂度为O(n),这里需要使用collections.deque()
class MyQueue:
    def __init__(self):
        self.queue = deque()
    def pop(self,value):
        if self.queue and value == self.queue[0]:
            self.queue.popleft()
    def push(self,value):
        # 在入队列之前先进行出队列的判定
        while self.queue and value > self.queue[-1]:
            self.queue.pop()
        self.queue.append(value)
    
    def front(self):
        return self.queue[0]

class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> 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

单调队列的设计原则:
pop():如果窗口移除的值等于单调队列的出口元素,那么队列弹出元素,否则不用任何操作
push():如果push的值大于入口元素的数值,那么就将队列出口的元素弹出,直到push元素的数值小于等于队列入口元素的数值为止

347. 前K个高频元素

难点1: 统计频率(map)
难点2: 对频率进行排序,只需要维护k个有序的集合就可以了,没有必要对所有的顺序进行维护。(大顶堆和小顶堆)
小顶堆: 本质是一个二叉树,根节点是数值最小的元素,在push元素的时候,pop顶的元素,那么剩余的元素就是我们在维护的k个元素。每push一个元素就需要pop一个元素。

在这里插入图片描述

# 大顶堆和小顶堆的区分情况
import heapq
class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        #要统计元素出现频率
        map_ = {} #nums[i]:对应出现的次数
        for i in range(len(nums)):
            map_[nums[i]] = map_.get(nums[i], 0) + 1
        
        #对频率排序
        #定义一个小顶堆,大小为k
        pri_que = [] #小顶堆
        
        #用固定大小为k的小顶堆,扫描所有频率的数值
        for key, freq in map_.items():
            heapq.heappush(pri_que, (freq, key))
            if len(pri_que) > k: #如果堆的大小大于了K,则队列弹出,保证堆的大小一直为k
                heapq.heappop(pri_que)
        
        #找出前K个高频元素,因为小顶堆先弹出的是最小的,所以倒序来输出到数组
        result = [0] * k
        for i in range(k-1, -1, -1):
            result[i] = heapq.heappop(pri_que)[1]
        return result

大小顶堆的创建:https://blog.csdn.net/wqylry/article/details/100007328
从二叉树到大小顶堆的调整
也可以直接使用heapq模块进行优先级队列的创建。

python collections库介绍

介绍: 实现特定目标的容器,在python内置的基础数据类型和方法上提供额外的高性能数据类型。

import collections
print(collections.__all__)
['deque', 'defaultdict', 'namedtuple', 'UserDict', 'UserList', 
'UserString', 'Counter', 'OrderedDict', 'ChainMap']

常用的两个模块deque和Counter

  1. deque:类似列表(list)的容器,实现了在两端快速添加(append)和弹出(pop)
from collections import deque
a = deque('abc')
a.append('d') # 在末尾添加元素
a.appendleft('d') # 将元素添加到左端
a.clear() # 移除所有的元素
a.copy() # 创建一份浅拷贝
a.count('a') # 统计a中等于‘a’的个数
a.index('a')
a.insert(a.'x')
a.pop()
a.popleft() # 如果没有元素则引发IndexError



  1. Counter:字典的子类,提供了可哈希对象的计数功能,可以用来进行统计计数
#上述这样计算有点嘛,下面的方法更简单,直接计算就行
L = ['red', 'blue', 'red', 'green', 'blue', 'blue'] 
Counter(L)
> Counter({'red': 2, 'blue': 3, 'green': 1}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值