代码随想录算法训练营Day10 | 232.用栈实现队列、225. 用队列实现栈

文章讲述了如何使用两个栈和两个队列分别实现先进先出(队列)和后入先出(栈)的数据结构,通过模拟栈和队列的操作,如push、pop、peek和empty,展示了如何在不支持特定数据结构的情况下利用基本操作实现复杂逻辑。
摘要由CSDN通过智能技术生成

232.用栈实现队列

题目:请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(pushpoppeekempty):

实现 MyQueue 类:

  • void push(int x) 将元素 x 推到队列的末尾
  • int pop() 从队列的开头移除并返回元素
  • int peek() 返回队列开头的元素
  • boolean empty() 如果队列为空,返回 true ;否则,返回 false

说明:

  • 你 只能 使用标准的栈操作 —— 也就是只有 push to toppeek/pop from topsize, 和 is empty 操作是合法的。
  • 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。

题目链接:232. 用栈实现队列

卡哥的视频链接:栈的基本操作! | LeetCode:232.用栈实现队列

  栈是一种仅支持在表尾进行插入和删除操作的线性表,这一端被称为栈顶,另一端被称为栈底。元素入栈指的是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;元素出栈指的是从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。栈中的元素遵守后进先出(LIFO)的原则.

  栈的底层有两种:分别是基于数组的顺序栈和基于链表的链式栈

解题思路:定义两个栈,一个入栈一个出栈,由于队列是先进先出的,要想通过栈实现,我们可以再定义一个栈,把输入栈的元素再通过输出栈重新输出,顺序就会和队列一模一样

代码示例:

import java.util.Stack;

public class zhan_duilie {
    //声明两个栈
    private Stack <Integer>A;
    private Stack <Integer>B;

//构造方法,用来初始化两个新栈
    public zhan_duilie() {
        A = new Stack<>();
        B = new Stack<>();
    }
//把x元素压入A栈中,A用于入栈,B用于出栈
    public void push(int x) {
        A.push(x);
    }
    public int pop() {
        int peek = peek(); // 调用peek()方法获取队头元素
        B.pop(); // 从B栈中弹出元素,模拟队列的出队操作
        return peek; // 返回队头元素的值
    }
    public int peek() {
        // 如果B栈不为空,直接返回B栈顶元素,即队头元素
        if (!B.isEmpty()) {
            return B.peek();
        }
        // 如果B栈为空,但A栈也为空,则队列为空,返回-1
        if (A.isEmpty()) {
            return -1;
        }
        // 如果B栈为空,但A栈不为空,则将A栈的所有元素依次弹出并压入B栈,直到A栈为空
        while (!A.isEmpty()) {
            B.push(A.pop());
        }
        // 返回B栈顶元素,即队头元素
        return B.peek();
    }
    public boolean empty() {
        // 如果A栈和B栈都为空,则队列为空
        return A.isEmpty() && B.isEmpty();
    }
}

代码逻辑详解:

  1. 初始化两个栈:

    在构造方法中,我们创建了两个栈,AB,用来模拟队列。

  2. 入队操作:

    当需要入队时,我们将元素压入栈A中。

  3. 出队操作:

    出队操作需要确保队列的先进先出原则。我们先检查栈B是否为空,如果不为空,直接从B栈中弹出元素;如果B栈为空,我们将栈A的元素依次弹出并压入B栈,然后再从B栈中弹出元素,确保了队列的先进先出顺序。

  4. 获取队头元素:

    我们首先检查栈B是否为空,如果不为空,直接返回B栈顶元素;如果B栈为空,我们将栈A的元素依次弹出并压入B栈,然后返回B栈顶元素,即为队头元素。

  5. 判断队列是否为空:

    我们只需检查两个栈是否都为空,若都为空则队列为空。

通过这些步骤,我们用两个栈实现了队列的基本功能,包括入队、出队、获取队头元素和判断队列是否为空。

leetcode提交记录:

小tips:

1.在队列中,出队操作应该返回队头元素,并将其从队列中移除。因此,在执行出队操作之前,我们需要先获取队头元素的值,以便在之后返回。否则,如果直接执行出队操作,我们就无法获取到出队的元素是什么,无法返回其值。

2.注意栈的定义和方法的具体使用

225.用队列实现栈

题目:

请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(pushtoppop 和 empty)。

实现 MyStack 类:

  • void push(int x) 将元素 x 压入栈顶。
  • int pop() 移除并返回栈顶元素。
  • int top() 返回栈顶元素。
  • boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。

注意:

  • 你只能使用队列的标准操作 —— 也就是 push to backpeek/pop from frontsize 和 is empty 这些操作。
  • 你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。

示例:

输入:
["MyStack", "push", "push", "top", "pop", "empty"]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 2, 2, false]

解释:
MyStack myStack = new MyStack();
myStack.push(1);
myStack.push(2);
myStack.top(); // 返回 2
myStack.pop(); // 返回 2
myStack.empty(); // 返回 False

提示:

  • 1 <= x <= 9
  • 最多调用100 次 pushpoptop 和 empty
  • 每次调用 pop 和 top 都保证栈不为空

题目链接:225. 用队列实现栈

卡哥的视频链接:队列的基本操作! | LeetCode:225. 用队列实现栈

题目思考:因为队列就像一个管道,怎么进去就怎么出来,所以我们要用两个队列,其中一个负责输出,一个负责储存,这样才能模拟实现栈的功能。

代码示例:

import java.util.LinkedList;
import java.util.Queue;

public class duilie_zhan {
    // 声明两个队列作为栈的辅助数据结构
    Queue<Integer> queue1 = new LinkedList<>();
    Queue<Integer> queue2 = new LinkedList<>();

    // 构造方法,初始化两个队列
    public duilie_zhan() {
        queue1 = new LinkedList<>();
        queue2 = new LinkedList<>();
    }

    // 入栈操作
    public void push(int x) {
        // 将新元素添加到队列2的末尾
        queue2.offer(x);
        // 将队列1的元素逐个出队并添加到队列2的末尾,确保新入栈的元素位于栈的顶部
        while (!queue1.isEmpty()) {
            queue2.offer(queue1.poll());
        }
        // 交换队列1和队列2,保持队列1始终为当前栈的主队列
        Queue<Integer> queueTemp;
        queueTemp = queue1;
        queue1 = queue2;
        queue2 = queueTemp;
    }
    // 获取栈顶元素
    public int top() {
        // 返回队列1的头部元素,即栈顶元素
        return queue1.peek();
    }
    // 判断栈是否为空
    public boolean empty() {
        // 如果队列1为空,则栈为空
        return queue1.isEmpty();
    }
}

代码逻辑详解:

  1. 入栈操作:

    • 当执行入栈操作时,首先将新元素加入到一个辅助队列中(这里是 queue2)。
    • 然后,我们需要确保新入栈的元素位于栈顶,因此将主队列(这里是 queue1)中的所有元素逐个出队,并依次加入到辅助队列的末尾。
    • 最后,为了保持栈的逻辑顺序,我们将主队列和辅助队列的引用进行交换,使得主队列成为当前栈的主队列。
  2. 获取栈顶元素:

    • 获取栈顶元素的操作是非常简单的,只需要返回主队列(这里是 queue1)的头部元素即可,因为头部元素即为栈顶元素。
  3. 判断栈是否为空:
    • 要判断栈是否为空,只需要检查主队列(queue1)是否为空即可。如果主队列为空,则表示栈为空。

总的来说,这段代码实现了使用两个队列来模拟栈的功能。在入栈操作中,我们使用了一个辅助队列来保持栈顺序的正确性,并且在需要时交换了主队列和辅助队列的引用。通过这种方式,我们可以利用队列的先进先出特性来模拟栈的后进先出行为。

leetcode提交记录:

小tips:

1.因为queue1是主队列,存储的全部的元素,所以取顶部元素、弹出元素和判断空都只需要对queue1进行操作

2.在对queue2进行添加新元素,把queue1的元素放入queue2中后,为了保证逻辑正确,我们要交换两个队列

3.注意队列的定义,没有圆括号,尖括号中要表明数据类型

代码随想录算法训练营是一个优质的学习和讨论平台,提供了丰富的算法训练内容和讨论交流机会。在训练营中,学员们可以通过观看视频讲解来学习算法知识,并根据讲解内容进行刷题练习。此外,训练营还提供了刷题建议,例如先看视频、了解自己所使用的编程语言、使用日志等方法来提高刷题效果和语言掌握程度。 训练营中的讨论内容非常丰富,涵盖了各种算法知识点和解题方法。例如,在第14天的训练营中,讲解了二叉树的理论基础、递归遍历、迭代遍历和统一遍历的内容。此外,在讨论中还分享了相关的博客文章和配图,帮助学员更好地理解和掌握二叉树的遍历方法。 训练营还提供了每日的讨论知识点,例如在第15天的讨论中,介绍了层序遍历的方法和使用队列来模拟一层一层遍历的效果。在第16天的讨论中,重点讨论了如何进行调试(debug)的方法,认为掌握调试技巧可以帮助学员更好地解决问题和写出正确的算法代码。 总之,代码随想录算法训练营是一个提供优质学习和讨论环境的平台,可以帮助学员系统地学习算法知识,并提供了丰富的讨论内容和刷题建议来提高算法编程能力。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [代码随想录算法训练营每日精华](https://blog.csdn.net/weixin_38556197/article/details/128462133)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值