leetcode刷题笔记之专题(2)堆栈(stack)和队列(Queue) Python实现

第二专题 堆栈(stack)和队列(Queue)

前导知识点:

  • Stack - First In Last Out(FILO)先进后出

所用到的数据结构:Array or Linked List

  • Queue-First In First Out(FIFO)先进后出

所用到的数据结构:Array or Doubly Linked List

在这里插入图片描述

1. leetcode20. 有效的括号(easy)

class Solution:
    def isValid(self, s: str) -> bool:
        partner = {')':'(',']':'[','}':'{'}
        stack = list()
        for i in s:
            if i in partner:
                if not stack or stack.pop() != partner[i]:
                    return False
            else:
                stack.append(i)
        return not stack

2. leetcode225. 用队列实现栈

解题思路:使用双队列,使用python语言求解的话,可以使用列表数据结构,因此为了满足队列的特性我们仅使用列表的append和pop(0)方法。

思路比较简单:我们仅需要维护一个queue1,在添加一个元素时,我们只需要将其添加到queue2中,然后通过将queue1中所有的数出队列到queue2中,后面通过交换queue1和queue2的指向就可。插入的时间复杂度为O(n),其余操作的时间复杂度为O(1)

class MyStack:

    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.queue1 = []
        self.queue2 = []

    def push(self, x: int) -> None:
        """
        Push element x onto stack.
        """
        self.queue2.append(x)
        while self.queue1:
            self.queue2.append(self.queue1.pop(0))
        self.queue1,self.queue2 = self.queue2,self.queue1


    def pop(self) -> int:
        """
        Removes the element on top of the stack and returns that element.
        """
        return self.queue1.pop(0)


    def top(self) -> int:
        """
        Get the top element.
        """
        return self.queue1[0]


    def empty(self) -> bool:
        """
        Returns whether the stack is empty.
        """
        return not self.queue1

3. leetcode232. 用栈实现队列

题目分析:

栈为先入后出,而队列是先进先出。要使用栈实现先入先出的队列的话,可以预定义两个栈,一个作为输入栈,一个作为输出栈。当压入数据时,则直接放在输入栈中。当使用pop, peek, empty输出时,则主要对输出栈进行操作:

class MyQueue:

    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.input_stack = []
        self.output_stack = []


    def push(self, x: int) -> None:
        """
        Push element x to the back of queue.
        """
        self.input_stack.append(x)

    def pop(self) -> int:
        """
        Removes the element from in front of queue and returns that element.
        """
        if self.output_stack:
            return self.output_stack.pop()
        else:
            while self.input_stack:
                self.output_stack.append(self.input_stack.pop())
            return self.output_stack.pop()
        


    def peek(self) -> int:
        """
        Get the front element.
        """
        if self.output_stack:
            return self.output_stack[-1]
        else:
            while self.input_stack:
                self.output_stack.append(self.input_stack.pop())
            return self.output_stack[-1]


    def empty(self) -> bool:
        """
        Returns whether the queue is empty.
        """
        return not self.output_stack and not self.input_stack

优先队列(PriorityQueue)

  • 正常入、按照优先级出

优先队列的实现机制:

Heap(Binary, Binomial, Fibonacci)

Binary Search Tree

4.从topK问题学习堆栈的思想以及python标准库方式与python实现笔记

5. 239. 滑动窗口最大值

方法1 使用优先队列——堆

维护一个大小为K的大根堆,对大根堆,每一次滑动窗口,即向堆中删除和加入元素,维护堆的结构的时间复杂度为O(logk),遍历的时间复杂度为O(n),因此总的时间复杂度为O(n*logk)

import heapq
class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        n = len(nums)
        # 初始化一个堆q
        q = [(-nums[i],i) for i in range(k)]
        heapq.heapify(q)

        res = [-q[0][0]]
        for i in range(k,n):
            heapq.heappush(q,(-nums[i], i))
            while q[0][1]<= i-k:
                heapq.heappop(q)
            res.append(-q[0][0])
        return res
方法2. 使用单调队列

维护一个堆,显然还有一些冗余在里面,因此我们可以维护一个队列,让队列的前面始终为当前滑动窗口最大的数字。每次我们比较接着进入队列的数据,如果比队列最前面的数都大,那么直接让队列为空,并将该数入队列。为了随时确定每一次操作,当前最大的数都还存在于滑动窗口中,维护队列时仅保存索引到队列中,方便进行判断。

from collections import deque
class Solution:
    def maxSlidingWindow(self, nums, k):
        n = len(nums)
        q = deque()
        for i in range(k): # 初始化一个双端队列
            while q and nums[q[-1]] <= nums[i]:
                q.pop()
            q.append(i)

        res = [nums[q[0]]]
        for i in range(k,n):
            while q and nums[q[-1]] < nums[i]:
                q.pop()
            q.append(i)
             
            while q[0] <= i-k:
                q.popleft()
            res.append(nums[q[0]])
        return res
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值