算法题:两个栈实现一个队列

这篇博客讨论了一种利用两个栈来实现队列操作的方法,包括push和shift操作。在入队(push)时,数据直接进入栈1;而出队(shift)时,若栈2为空,则将栈1的所有元素依次弹出并压入栈2,最后从栈2弹出顶部元素完成出队。这种方法在push操作时具有O(1)的时间复杂度,但在shift操作时可能达到O(n)。博客通过单元测试验证了该实现的正确性和效率,并分析了其时间与空间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

该题的解题思路用到了数据结构栈和队列的概念,请查看 队列

/**
 * @description 两个栈实现一个队列
 * @author lsr
 */

export class Queue {
  private stack1: number[] = []
  private stack2: number[] = []

  /**
   * 入队
   * @param num num
   */
  push(num: number) {
    this.stack1.push(num)
  }

  /**
   * 出队
   * @returns number | null
   */
  shift(): number | null {
    const stack1 = this.stack1
    const stack2 = this.stack2

    // 如果 stack2 还有值,直接出队,如果没值复制 stack1,再出队
    if (!stack2.length) {
      while (stack1.length) {
        const n = stack1.pop()
        if (n !== undefined) stack2.push(n)
      }
    }

    const res = stack2.pop()
    return res || null
  }

  get length(): number {
    return this.stack1.length + this.stack2.length
  }
}

// 功能测试
// const q = new Queue()
// q.push(100)
// q.push(200)
// q.push(300)
// q.push(400)
// q.push(500)
// console.log(q.length)
// console.log(q.shift())
// console.log(q.length)
// console.log(q.shift())
// console.log(q.shift())
// console.log(q.shift())
// console.log(q.shift())
// console.log(q.shift())
// q.push(600)
// q.push(700)
// q.push(800)
// console.log(q.length)
// console.log(q.shift())
// console.log(q.shift())

单元测试

/**
 * @description 两个栈实现一个队列 test
 * @author lsr
 */

import { Queue } from '@/01-algorithm/twoStacks-oneQueue'

describe('两个栈实现一个队列', () => {
  it('测试 push 和 length', () => {
    const q = new Queue()
    q.push(100)
    expect(q.length).toBe(1)
    q.push(200)
    q.push(300)
    expect(q.length).toBe(3)
  })

  it('测试 shift 和 length', () => {
    const q = new Queue()
    q.push(100)
    q.push(200)
    q.push(300)
    expect(q.length).toBe(3)
    const n1 = q.shift()
    const n2 = q.shift()
    const n3 = q.shift()
    expect(n1).toBe(100)
    expect(n2).toBe(200)
    expect(n3).toBe(300)
    expect(q.length).toBe(0)
  })

  it('测试 shift 最后一个元素后,继续删除', () => {
    const q = new Queue()
    q.push(100)
    q.push(200)
    q.push(300)
    expect(q.length).toBe(3)
    const n1 = q.shift()
    const n2 = q.shift()
    const n3 = q.shift()
    const n4 = q.shift()
    expect(n1).toBe(100)
    expect(n2).toBe(200)
    expect(n3).toBe(300)
    expect(q.length).toBe(0)
    expect(n4).toBeNull()
    expect(q.length).toBe(0)
  })

  it('测试 shift 最后一个元素后,再push', () => {
    const q = new Queue()
    q.push(100)
    q.push(200)
    q.push(300)
    expect(q.length).toBe(3)
    const n1 = q.shift()
    const n2 = q.shift()
    const n3 = q.shift()
    expect(n1).toBe(100)
    expect(n2).toBe(200)
    expect(n3).toBe(300)
    expect(q.length).toBe(0)
    q.push(400)
    q.push(500)
    expect(q.length).toBe(2)
  })

  it('测试 shift 最后一个元素后,再 push,再 shift', () => {
    const q = new Queue()
    q.push(100)
    q.push(200)
    q.push(300)
    expect(q.length).toBe(3)
    const n1 = q.shift()
    const n2 = q.shift()
    const n3 = q.shift()
    expect(n1).toBe(100)
    expect(n2).toBe(200)
    expect(n3).toBe(300)
    expect(q.length).toBe(0)
    q.push(400)
    q.push(500)
    expect(q.length).toBe(2)
    const n4 = q.shift()
    expect(n4).toBe(400)
    expect(q.length).toBe(1)
  })
})

复杂度分析

  • 时间复杂度:push O(1)、shift O(n)
  • 空间复杂度:O(n)

划重点

  • 队列
  • 逻辑结构 vs 物理结构
  • 将思路在纸上画出来
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值