栈和队列的理论基础
232. 用栈实现队列
链接
文章链接
题目链接
第一想法
因为只能用那几种方法,所以只能模拟了,想法是准备两个栈a和b,当执行pop和peek时先将原本的存储栈a通过pop导入b,此时b的top就是所需元素,代码如下:
class MyQueue {
arr:number[]
list:number[]
constructor() {
this.list =[]
this.arr=[]
}
push(x: number): void {
this.list.push(x)
}
pop(): number {
for(let i=this.list.length-1;i>=0;i--){
this.arr.push(this.list.pop() as number)
}
let num:number=this.arr.pop() as number
for(let i=this.arr.length-1;i>=0;i--){
this.list.push(this.arr.pop() as number)
}
return num
}
peek(): number {
for(let i=this.list.length-1;i>=0;i--){
this.arr.push(this.list.pop() as number)
}
let num:number=this.arr.pop() as number
this.list.push(num)
for(let i=this.arr.length-1;i>=0;i--){
this.list.push(this.arr.pop() as number)
}
return num
}
empty(): boolean {
return this.list.length==0
}
}
看完文章后的想法
文章的想法比我的全面和详细,我pop之后还会把b导入a,其实是完全不用的,因为b导入a并不会影响pop和peek,而且代码是可以复用的,所以不用写那么多重复代码。代码如下:
class MyQueue {
stdIn:number[] //用于模拟入栈
stdOut:number[] //用于模拟出栈
constructor() {
this.stdIn =[]
this.stdOut=[]
}
push(x: number): void {
this.stdIn.push(x)
}
pop(): number {
if(this.stdOut.length===0){ //当出栈里没有元素时再从入栈导入
while(this.stdIn.length!=0){
this.stdOut.push(this.stdIn.pop())
}
}
return this.stdOut.pop()
}
peek(): number {
let num:number=this.pop() //调用刚刚的pop方法
this.stdOut.push(num)
return num
}
empty(): boolean {
return this.stdIn.length==0&&this.stdOut.length==0
}
}
下面附代码随想录里面的图帮助理解:
思考
用栈模拟队列,要理解栈和队列的区别,一个先进先出(queue),一个后进先出(stack),所以要用栈模拟队列,一定要有两个栈,一个模拟入栈,一个模拟出栈。总体上不难,但是要把细节想好不容易。
225. 用队列实现栈
链接
文章链接
题目链接
第一想法
这一道题是用队列模拟栈,队列先进先出,栈后进先出,这道题和栈模拟队列是不一样的,队列既可以进入又可以出去,所以只需要一个队列queue就行了
class MyStack {
queue:number[]
constructor() {
this.queue=[]
}
push(x: number): void {
this.queue.push(x)
}
pop(): number {
let len:number=this.queue.length-1 //pop将要出去的元素再填入队列中
while(len>0){
this.queue.push(this.queue.shift() as number) //出去再进来
len--
}
return this.queue.shift() as number //最后一个元素只出不进
}
top(): number {
//和栈模拟队列一样
let num:number=this.pop()
this.queue.push(num)
return num
}
empty(): boolean {
return this.queue.length===0
}
}
看完文章后的想法
我的想法和代码随想录中优化完的思路是一致的,同时代码随想录中也有使用了两个队列完成栈的任务,于是乎我也写了一遍:
class MyStack {
queue:number[]
queue2:number[]
constructor() {
this.queue=[]
this.queue2=[]
}
push(x: number): void {
this.queue.push(x)
}
pop(): number {
while(this.queue.length!=1){
this.queue2.push(this.queue.shift() as number)
}
let num:number=this.queue.shift() as number
this.queue=this.queue2
this.queue2=[]
return num
}
top(): number {
let num:number=this.pop()
this.push(num)
return num
}
empty(): boolean {
return this.queue.length===0
}
}
下面是代码随想录中的模拟的gif图片
思考
这道题不难,用一个队列或两个队列都可以解决这个问题,同时也要理解先进先出和后进后出的区别,仔细看完文章后会有很深的感触。
今日总结
今天的题就两道,不算太难,但是要理解栈stack的后进先出和队列queue的先进先出的真正含义,这两道题的理论意义大于实践意义,要明白其中的原理。同时学到了一种写代码的习惯,减少重复代码(封装函数等方法)。