在之前刷力扣的过程中,我每刷道题都是先看题解然后再去边写边看,很多内容根本没消化,在进度上欺骗自己,感觉之前刷的都忘了,能力没有什么提升,现在还是一道都不会做。所以这次报了卡哥的算法训练营,希望能够按计划地有效刷题。本次刷题,我用的是 Java 语言解题,有余力的话也可能会加上 C++ 的题解。以下是算法训练营第十天的刷题记录和思考笔记。
一、栈和队列基本原理
栈是先进后出(LIFO),队列是先进先出(FIFO)。
Java 使用栈时推荐 Deque 双端队列而不是 Stack,因为 Stack 继承自 Vector,破坏了类的封装性;其次,Stack 是类,Deque 是接口,接口可以屏蔽实现细节。ArrayDeque
会比 LinkedList
在除了删除元素这一点外会快一点
1 | Deque<Integer> queue1 = new ArrayQueue<>(); |
二、232 用栈实现队列
题目
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push
、pop
、peek
、empty
):
实现 MyQueue
类:
void push(int x)
将元素 x 推到队列的末尾int pop()
从队列的开头移除并返回元素int peek()
返回队列开头的元素boolean empty()
如果队列为空,返回true
;否则,返回false
你只能使用标准的栈操作 —— 也就是只有 push to top
, peek/pop from top
, size
, 和 is empty
操作是合法的。
1 | 输入: |
解题思路
将一个栈当作输入栈,用于压入 push 传入的数据;另一个栈当作输出栈,用于 pop 和 peek 操作。每次 pop 或 peek 时,若输出栈为空则将输入栈的全部数据依次弹出并压入输出栈,这样输出栈从栈顶往栈底的顺序就是队列从队首往队尾的顺序。
1 | class MyQueue { |
peek()
的实现,直接复用了 pop()
, 要不然,对 stackOut 判空的逻辑又要重写一遍。因此,一定要懂得复用,功能相近的函数要抽象出来。
三、225 用队列实现栈
题目
请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push
、top
、pop
和 empty
)。
实现 MyStack
类:
void push(int x)
将元素 x 压入栈顶。int pop()
移除并返回栈顶元素。int top()
返回栈顶元素。boolean empty()
如果栈是空的,返回true
;否则,返回false
。
你只能使用队列的基本操作 —— 也就是 push to back
、peek/pop from front
、size
和 is empty
这些操作。
1 | 输入: |
解题思路
使用一个队列实现栈的操作。入栈操作时,首先获得入栈前的元素个数 n,然后将元素入队到队列,再将队列中的前 n 个元素(即除了新入栈的元素之外的全部元素)依次出队并入队到队列,此时队列的前端的元素即为新入栈的元素,且队列的前端和后端分别对应栈顶和栈底。
由于每次入栈操作都确保队列的前端元素为栈顶元素,因此出栈操作和获得栈顶元素操作都可以简单实现。出栈操作只需要移除队列的前端元素并返回即可,获得栈顶元素操作只需要获得队列的前端元素并返回即可(不移除元素)。
由于队列用于存储栈内的元素,判断栈是否为空时,只需要判断队列是否为空即可。
1 | class MyStack { |