【水滴计划 | 每日两题】:用栈实现队列、用队列实现栈

130 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第31天,点击查看活动详情

1、写在前面

大家好,我是翼同学,这里是【水滴计划 | 刷题日志】

每日两题,拒绝摆烂。

2、内容

2.1、题目一:用栈实现队列

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

(1) 描述

image.png

(2) 举例

image.png

image.png

(3) 解题

这道题要求我们使用栈结构来模拟队列的行为,考察我们对栈和队列的掌握程度。

如果单纯使用一个栈结构,不足以解决这道题,因此这里应该使用两个栈,分别是输入栈输出栈

具体的思路如下:

  • 入队push():当我们需要将元素x压入队列的末尾时,只需将元素压入输入栈即可;
  • 出队pop():当我们需要移除队列的首元素时,则需判断输出栈是否为空?如果输出栈为空,则需要将输入栈的元素全部压入输出栈,再从输出栈弹出栈顶元素,此时就实现了出队操作。否则,如果输出栈不为空,则直接弹出输出栈的栈顶元素即可;
  • 返回队列首元素peek():该函数的功能和pop()函数类似,稍微修改即可;
  • 判断队列是否为空empty():如果输入栈和输出栈都为空,则证明该队列为空,返回ture;否则返回false
class MyQueue {
public:
    stack<int> StackIn;     // 定义一个输入栈
    stack<int> stackOut;    // 定义一个输出栈

    // 构造函数
    MyQueue() {
        // ...
    }
    
    // 入队
    void push(int x) {
        StackIn.push(x);    // 将数据元素压入输入栈
    }
    
    // 弹出队列首元素
    int pop() {
        // 当输出栈为空时
        if (stackOut.empty()) {
            // 将输入栈中的全部元素压到输入栈中
            while(!StackIn.empty()) {
                // 将输入栈的栈顶元素压入输入栈中
                stackOut.push(StackIn.top());
                // 弹出输入栈的栈顶元素
                StackIn.pop();
            }
        }
        // pop()函数需要返回队列首元素,因此先用result暂存这个值
        int result = stackOut.top();
        // 弹出输出栈的栈顶元素
        stackOut.pop();
        // 返回队列的首元素
        return result;
    }
    
    int peek() {
        // 当输出栈为空时
        if (stackOut.empty()) {
            // 将输入栈中的全部元素压到输入栈中
            while(!StackIn.empty()) {
                // 将输入栈的栈顶元素压入输入栈中
                stackOut.push(StackIn.top());
                // 弹出输入栈的栈顶元素
                StackIn.pop();
            }
        }
        // 返回输出栈的栈顶元素
        return stackOut.top();
    }
    
    bool empty() {
        // 如果输入栈和输出栈都为空,则该模拟队列就为空
        if(StackIn.empty() && stackOut.empty()) {
            return true;
        } 
        // 否则返回false
        else {
            return false;
        }
    }
};

/**
 * Your MyQueue object will be instantiated and called as such:
 * MyQueue* obj = new MyQueue();
 * obj->push(x);
 * int param_2 = obj->pop();
 * int param_3 = obj->peek();
 * bool param_4 = obj->empty();
 */

image.png

2.2、题目二:用队列实现栈

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

(1) 描述

image.png

image.png

(2) 举例

image.png

image.png

(3) 解题

这道题要求我们利用队列来实现栈的特性。

前文我们利用了两个栈来模拟一个队列,而在这道题中,我们利用一个队列,其实就可以模拟栈了。由于队列中数据的存取规则是“先进先出”,此时将一个队列中的元素存入另一个队列,其实元素的顺序没有发生改变,也无法变成“先进后出”的栈存取规则。因此,如果仅利用一个队列结构来模拟栈结构时,在弹出栈顶元素时,只需将队列的队头元素添加到队尾,重复这个过程,直到遇到最后一个元素,就将该元素弹出即可实现栈的pop()函数。

class MyStack {
public:
    queue<int> q;   // 工作队列
    MyStack() {
        // ...
    }
    // 进栈操作
    void push(int x) {
        q.push(x);
    }
    // 弹出栈顶元素
    int pop() {
        // 将末尾元素之前的所有元素,按顺序添加到队列的尾部,并依次弹出
        for(int i = 1; i < q.size(); i++) {
            q.push(q.front());
            q.pop();
        }

        // 经过 for 循环后,队列首元素已变成了之前的队尾元素
        // 这样就实现了栈的 “后进先出” 规则,此时弹出的队头元素就是按照栈的顺序弹出的

        int top = q.front();
        q.pop();
        return top;
    }

    // 返回栈顶元素,调用 back() 函数即可
    int top() {
        return q.back();
    }

    // 判断栈是否为空,调用 empty() 即可
    bool empty() {
        return q.empty();
    }
};

image.png

3、写在最后

好了,今天就刷到这里,明天再来。