leetcode栈和队列

文章介绍了如何使用栈、队列、双端队列以及堆数据结构(如小顶堆和大顶堆)解决编程问题,包括找到最小值、验证书序、滑动窗口最大值、自动结算机操作和中位数计算。作者通过实例展示了如何在实际问题中巧妙运用这些数据结构。
摘要由CSDN通过智能技术生成

1.取最小值。用两个栈来实现,一个普通存数,一个只存相对小的数。不要忘了栈是用列表实现的,列表也能pop,并且有返回值。思路明明正确但提交了好多次,,错在push判断条件上写错了,or左右两边的条件不能随便对调,有顺序的

if not self.tmp or x <= self.tmp[-1]:
class MinStack:
    def __init__(self):
        self.A, self.B = [], []

    def push(self, x):
        self.A.append(x)
        if not self.B or self.B[-1] >= x:    # B 为空或者发现更小的数X,则入栈B
            self.B.append(x)

    def pop(self):
        if self.A.pop() == self.B[-1]:    # 可以直接用列表的pop
            self.B.pop()

    def top(self):
        return self.A[-1]

    def getMin(self):
        return self.B[-1]

2.判断是否能按方法取得/ 判断栈的进出是否合理。注意循环的安放,用for来控制进栈,内置while判断出栈,每出栈一次,计数 i +1

class Solution(object):

    def validateBookSequences(self, putIn, takeOut):
        """
        :type putIn: List[int]
        :type takeOut: List[int]
        :rtype: bool
        """
        i = 0
        stack = []
        for num in putIn:
            stack.append(num)
            while stack and stack[-1] == takeOut[i]:    # 判断是否出栈
                stack.pop()
                i += 1  # 计数i要放在出栈后
        return not stack    # 如果可以取出则stack为空 

3.滑动窗口找窗口最大值(望远镜中的最高海拔)。用暴力可以求,用指针指向窗口的最后一个元素,用两重循环(一重移动窗口,一重建立窗口列表用于找最大值)返回每次查找的窗口最大值。很慢。

class Solution(object):
    def maxAltitude(self, heights, limit):
        tmp = []
        t = []
        if not heights:
            return tmp
        for cnt in range(limit-1, len(heights)):
            # tmp.append(max(heights[cnt-2], heights[cnt-1], heights[cnt]))
            for i in range(limit):
                t.append(heights[cnt-i])
            tmp.append(max(t))
            t = []
        return tmp

K神用的队列求解。用一个双端队列来存一个升序队列:遇到小的数加入队尾,遇到大的数弹出队尾,并加上大的数。每次窗口返回最大值都返回双端队列deque的队头。

import collections
class Solution:
    def maxAltitude(self, heights, limit):
        if not heights or limit == 0: return []
        deque = collections.deque()    # 需要import collections
        # 未形成窗口
        for i in range(limit):
            while deque and deque[-1] < heights[i]:
                deque.pop()        
            deque.append(heights[i])
        res = [deque[0]]
        # 形成窗口后
        for i in range(limit, len(heights)):
            if deque[0] == heights[i - limit]:
                deque.popleft()
            while deque and deque[-1] < heights[i]:
                deque.pop()
            deque.append(heights[i])
            res.append(deque[0])
        return res

4.自动结算机,用队列实现一系列队列的操作(找最大值,加入队尾,移出队首),要求O(1)。用双端队列deque的pop 和popleft 协助实现O(1)。

# 在本地调试要导入库
import queue
from collections import deque
class Checkout(object):
    def __init__(self):
        self.queue = queue.Queue() # 定义普通队列
        self.deque = deque()    # 定义双端队列

    def get_max(self):
        """
        :rtype: int
        """
        return self.deque[0] if self.deque else -1


    def add(self, value):
        """
        :type value: int
        :rtype: None
        """
        self.queue.put(value)    # queue加队尾
        while self.deque and self.deque[-1] < value:
            self.deque.pop()    # 队尾弹出较小数
        self.deque.append(value)    # 加入deque


    def remove(self):
        """
        :rtype: int
        """
        if not self.queue:
            return -1
        val = self.queue.get()  # 首元素出列
        if self.deque[0] == val:
            self.deque.popleft()    # 当移出的数为最大值时,deque的队首也要移出
        return val

5.找中位数。通过heapq模块(小顶堆,最小元素在根节点)构造一个大顶堆(小顶堆取反)和一个小顶堆保证数据有序,通过根节点取中位数

堆的知识:heapq --- 堆队列算法 — Python 3.12.0 文档

 from heapq import *

class MedianFinder:
    def __init__(self):
        self.A = []  # 小顶堆,保存较大的一半
        self.B = []  # 大顶堆,保存较小的一半

    def addNum(self, num):
        if len(self.A) != len(self.B):
            # heapq.heappush(heap, item) 将 item 的值加入 heap 中,保持堆的不变性。
            heappush(self.A, num)
            heappush(self.B, -heappop(self.A))
            # heapq.heappop(heap) 弹出并返回 heap 的最小的元素,保持堆的不变性
        else:
            heappush(self.B, -num)
            heappush(self.A, -heappop(self.B))

    def findMedian(self):   
        return self.A[0] if len(self.A) != len(self.B) else (self.A[0] - self.B[0]) / 2.0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值