day09-数据结构力扣

栈与队列

栈的基础知识

栈是一种后进先出(LIFO)的数据结构,只允许在栈顶进行插入和删除操作。栈的基本操作包括:

  • push(x):将元素x压入栈顶。

  • pop():弹出栈顶元素并返回。

  • peek()top():返回栈顶元素但不删除。

  • isEmpty():判断栈是否为空。

栈的典型应用场景包括:

  • 函数调用栈:递归或函数调用时的上下文存储。

  • 括号匹配:检查表达式中的括号是否成对出现。

  • 表达式求值:中缀表达式转后缀表达式并计算。

  • 深度优先搜索(DFS):用于模拟递归或回溯。

队列的基础知识

队列是一种先进先出(FIFO)的数据结构,允许在队尾插入元素,在队首删除元素。队列的基本操作包括:

  • enqueue(x):将元素x插入队尾。

  • dequeue():删除队首元素并返回。

  • front():返回队首元素但不删除。

  • isEmpty():判断队列是否为空。

队列的典型应用场景包括:

  • 广度优先搜索(BFS):按层次遍历树或图。

  • 任务调度:处理按顺序到达的任务。

  • 滑动窗口问题:如求滑动窗口的最大值或最小值。

双端队列(Deque)

双端队列是一种允许在两端进行插入和删除操作的数据结构。结合了栈和队列的特性,常见操作包括:

  • addFirst(x):在队首插入元素。

  • addLast(x):在队尾插入元素。

  • removeFirst():删除队首元素。

  • removeLast():删除队尾元素。

双端队列的应用场景包括:

  • 滑动窗口问题:如LeetCode中的"239. 滑动窗口最大值"。

  • 实现栈或队列:通过限制操作端模拟栈或队列。

232.用栈实现队列

题目链接232. 用栈实现队列 - 力扣(LeetCode)

思路

用两个栈去实现一个队列,一个是in,一个是out,但是需要注意,必须把in里面的全部放到out,不然出来的顺序就会乱。

在push数据的时候,只要数据放进输入栈就好,但在pop的时候,操作就复杂一些,输出栈如果为空,就把进栈数据全部导入进来(注意是全部导入),再从出栈弹出数据,如果输出栈不为空,则直接从出栈弹出数据就可以了。

最后如何判断队列为空呢?如果进栈和出栈都为空的话,说明模拟的队列为空了。

写题

1.self.stack_out,有时候要把self写漏

2.还有 ans=self.pop(),我刚刚把他写成了ans=self.stack_out.pop()然后报错,说是为空什么的

  • self.stack_out.pop()只操作出队栈 ,不管入队栈有没有数据,不会自动倒数据

  • self.pop()完整的出队逻辑 ,会自动判断、自动把 stack_in 倒入 stack_out是安全、完整的出队方法

python 复制代码
class MyQueue:

    def __init__(self):
        self.stack_in=[]
        self.stack_out=[]

    def push(self, x: int) -> None:
        self.stack_in.append(x)

    def pop(self) -> int:
        if self.empty():  # 如果队列为空,直接返回None
            return None
        if self.stack_out:  # 如果出队栈有元素,直接弹出栈顶(队首)
            return self.stack_out.pop()
        else:  # 如果出队栈为空,将入队栈所有元素倒入出队栈
            for i in range(len(self.stack_in)):
                self.stack_out.append(self.stack_in.pop())
            return self.stack_out.pop()  # 弹出出队栈顶,即队首元素

    def peek(self) -> int:
        ans=self.pop()  # 先调用pop临时取出队首元素
        self.stack_out.append(ans)  # 将取出的元素放回出队栈,不删除
        return ans  # 返回队首元素

    def empty(self) -> bool:
        return not(self.stack_in or self.stack_out)


# Your MyQueue object will be instantiated and called as such:
# obj = MyQueue()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.peek()
# param_4 = obj.empty()

225. 用队列实现栈

题目链接225. 用队列实现栈 - 力扣(LeetCode)

思路

把前面size-1个元素弹出来,加到队列的后面,再把交换顺序之后的第一个取出来。

写题

这里用了一个队列,感觉这个popleft()挺好用的

python 复制代码
from collections import deque  # 必须导入才能用deque

class MyStack:

    def __init__(self):
        self.que=deque()

    def push(self, x: int) -> None:
        self.que.append(x)

    def pop(self) -> int:
        if self.empty():  # 如果栈为空,返回None
            return None
        for i in range(len(self.que)-1):  # 把除最后一个外的所有元素,依次移到队列尾部
            self.que.append(self.que.popleft())
        return self.que.popleft()  # 弹出此时队首元素(原栈顶)

    def top(self) -> int:
        if self.empty():  # 如果栈为空,返回None
            return None
        for i in range(len(self.que)-1):  # 把除最后一个外的所有元素,依次移到队列尾部
            self.que.append(self.que.popleft())
        temp=self.que.popleft()  # 取出队首(栈顶)暂存
        self.que.append(temp)  # 再放回队列,保持结构不变
        return temp  # 返回栈顶元素

    def empty(self) -> bool:
        return not self.que


# Your MyStack object will be instantiated and called as such:
# obj = MyStack()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.top()
# param_4 = obj.empty()

20. 有效的括号

题目链接 20. 有效的括号 - 力扣(LeetCode)

思路

虽然知道要用到栈,但是代码具体怎么写,括号具体怎么判断我还是不会

遍历,比如遇到'['就把与他匹配的']'加入栈中,下一次遇到方括号,判断判断是否有匹配的方括号,有就消除,没有就return False

最后再判断栈是否为空,为空,说明全都匹配了;不为空,说明还有括号没有匹配。

如果输入的括号个数是奇数,那一定不匹配

写题

python 复制代码
class Solution:
    def isValid(self, s: str) -> bool:
        stack=[]
        if len(s)%2==1:
            return False
        for items in s:
            if items =='[':
                stack.append(']')
            elif items == '(':
                stack.append(')')
            elif items =='{':
                stack.append('}')
            # 栈为空 或 栈顶符号与当前右括号不匹配 → 括号不合法
            elif not stack or stack[-1]!=items:
                return False
            # 括号匹配成功 → 弹出栈顶的匹配符号
            else:
                stack.pop()
        # 遍历结束后栈为空 → 所有括号都匹配,返回True;否则返回False
        return True if not stack else False

1047. 删除字符串中的所有相邻重复项

题目链接 1047. 删除字符串中的所有相邻重复项 - 力扣(LeetCode)

思路

字母不在栈中,或者栈最后一个不和输入字母匹配,都应该加入栈中

其余情况,把字母弹出去。

写题

通过了一部分的测试样例

python 复制代码
class Solution:
    def removeDuplicates(self, s: str) -> str:
        stack=[]
        for i in s:
            if i not in stack:
                stack.append(i)
            elif not stack and stack[-1]!=i:
                continue
            else:
                stack.pop()
        return ''.join(stack)

我运行了一下没有通过的测试用例,发现是加入元素时判断条件不对,反而把一个元素弹出。

然后我发现其实字母不在栈里面或者

是栈最后一个元素不和进入的字母匹配

都应该加入栈中

python 复制代码
class Solution:
    def removeDuplicates(self, s: str) -> str:
        stack=[]
        for i in s:
            if i not in stack or stack[-1]!=i:
                stack.append(i)
            else:
                stack.pop()
        return ''.join(stack)
相关推荐
旖-旎3 小时前
位运算(判断字符是否唯一)(1)
c++·算法·leetcode·位运算
词元Max3 小时前
1.4 核心名词解释:Token、RAG、Agent、MCP是什么
人工智能·算法
小捏哩3 小时前
死锁检测组件的设计
linux·网络·数据结构·c++·后端
mzhan0173 小时前
Linux: sched: pick_next_task_fair 这个函数的功能
linux·运维·算法
Wect3 小时前
LeetCode 4. 寻找两个正序数组的中位数:二分优化思路详解
前端·算法·typescript
ZPC82103 小时前
moveitcpp 没办法执行的问题
人工智能·pytorch·算法·机器人
左左右右左右摇晃3 小时前
Java线程池工作原理与回收机制
java·jvm·数据结构
智者知已应修善业3 小时前
【C++非递归剪枝问题凑钱方案数】2024-7-18
c语言·c++·经验分享·笔记·算法·剪枝
Yolo_TvT3 小时前
C++:缺省参数
开发语言·c++·算法