Leecode 232. 用栈实现队列

题目描述

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

实现 MyQueue 类:

void push(int x) 将元素 x 推到队列的末尾

int pop() 从队列的开头移除并返回元素

int peek() 返回队列开头的元素

boolean empty() 如果队列为空,返回 true ;否则,返回 false

说明:

只能 使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。

你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。

  • 示例 1:

输入:

["MyQueue", "push", "push", "peek", "pop", "empty"]

[[], [1], [2], [], [], []]

输出:

[null, null, null, 1, 1, false]

  • 解释:

MyQueue myQueue = new MyQueue();

myQueue.push(1); // queue is: [1]

myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue)

myQueue.peek(); // return 1

myQueue.pop(); // return 1, queue is [2]

myQueue.empty(); // return false

解题思路与代码展示

本题要求使用栈来实现队列,首先理解并区分栈和队列的区别。栈的主要特点在于先进后出,而队列却是先进先出,画出图像来看相当于栈只有一个出口(同时也是入口),而队列则有一个出口和一个入口。因此为了使用栈来实现队列,我们考虑使用两个栈搭配一同实现一个队列。

考虑准备两个栈,分别称之为栈1和栈2,用于模拟一个先进先出的队列。一个数据到达时直接进入栈2中,位于栈2的顶部。而要取出一个数据时,直接取出栈1中最顶部的数据。而如果取数据时栈1中已经为空,那么此时需要将栈2中的数据逐个出栈同时立即进入栈1中,这样就可以使得此时栈1中最顶部的数据为原先最先进入栈2中的数据,从而实现了先进先出的效果。而如果要判断当前队列是否为空,只要两个栈都为空,那么当前队列就为空。

根据上面思路,可以实现这个队列的代码如下:

class MyQueue {
public:
stack<int> stkS1;
stack<int> stkS2;
MyQueue() {
} void push(int x) {
stkS1.push(x); // 入队列相当于直接进入栈1
} int pop() {
if(!stkS2.empty()){ // 出队列相当于从栈2直接pop,但需要确保栈2不为空
int re = stkS2.top();
stkS2.pop();
return re;
}
while(!stkS1.empty()){ // 如果栈2为空,则将栈1中的元素全部出栈并压入栈2中,最后再从栈2取出
stkS2.push(stkS1.top());
stkS1.pop();
}
int re = stkS2.top();
stkS2.pop();
return re;
} int peek() {
if(stkS2.empty()){ // 如果栈2为空,则将栈1中的元素全部取出放入栈2中
while(!stkS1.empty()){
stkS2.push(stkS1.top());
stkS1.pop();
}
}
return stkS2.top(); // 栈2顶端即为队列头的元素
} bool empty() { // 如果两个栈都为空,则队列为空
if(stkS2.empty() && stkS1.empty()) return true;
return false;
}
};

上面代码即可使用两个栈来实现一个队列及其中的操作。

Leecode 225. 用队列实现栈

题目描述:

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

  • 实现 MyStack 类:

void push(int x) 将元素 x 压入栈顶。

int pop() 移除并返回栈顶元素。

int top() 返回栈顶元素。

boolean empty() 如果栈是空的,返回 true ;否则,返回 false

  • 注意:

你只能使用队列的标准操作 —— 也就是 push to back、peek/pop from front、size 和 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

解题思路与代码展示:

本题要求使用队列来实现栈,对于栈中所需要的实现的push()我们可以直接和队列的push()等同,只管将元素放入队列当中即可;同样操作的还有栈的empty()也直接使用队列的empty()函数即可。对于栈的top(),即刚放入栈中的元素,可以使用队列的back()来实现。唯一麻烦的在于使用队列来实现出栈的操作,出栈需要将队列中最后一个元素输出,而保留其他元素,考虑将队列中的每一个元素都从队列的最前方出队并从后方入队,最后即可将要出栈的元素顶到队列最前,此时再进行一次出队操作即可。由此我们可以得到下面代码实现:

class MyStack {
public:
queue<int> q;
MyStack() {
} void push(int x) {
q.push(x); // 直接使用入队列来表示入栈
} int pop() { // 如果要进行出栈操作,需要取出队列中的最后一个元素
for(int i = 0; i < q.size() - 1; i++ ){ // 将队列中长度-1个元素出队列,并逐一重新进入队列
int x = q.front();
q.pop();
q.push(x);
}
int x = q.front(); // 此时队列中的第一个元素即为刚进入队列中的元素,将其出栈
q.pop();
return x;
} int top() {
return q.back(); // queue中可以直接使用back来调用队列尾的元素
} bool empty() {
return q.empty(); // 栈空等价于队列也空
}
};

Leecode 20. 有效的括号

题目描述

给定一个只包括 '('')''{''}''['']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。
  3. 每个右括号都有一个对应的相同类型的左括号。
  • 示例 1:

输入:s = "()"

输出:true

  • 示例 2:

输入:s = "()[]{}"

输出:true

  • 示例 3:

输入:s = "(]"

输出:false

  • 示例 4:

输入:s = "([])"

输出:true

解题思路与代码实现

由于字符串中只有这三种左右括号,那么我们使用一个栈,在扫描遍历字符串的时根据当前字符是左括号还是右括号来进行相应的操作,即:

  • 如果当前为左括号,则进入栈中,等待后续被相应的右括号匹配
  • 如果当前为右括号,则查看栈顶部是否为对应的左括号,
    • 如果不是则说明此时的字符串不满足条件
    • 如果是则将栈中的左括号出栈,并继续遍历下一个字符
  • 当遍历完整个字符串后,还要检查栈中是否还有剩余未被匹配的左括号,如果还有的话说明也不符合条件
  • 等以上检查全部结束,则说明该字符串满足条件,返回true

根据上面这个算法思想,即可得到下面代码:

class Solution {
public:
bool isValid(string s) {
stack<char> stk; // 初始化栈
for(int i = 0; i < s.size(); i++){
if(s[i] == '{' || s[i] == '(' || s[i] == '[') stk.push(s[i]); // 如果是左括号则入栈
else{ // 如果是右括号,则需要继续判断栈中的情况
if(stk.empty()) return false; // 如果此时栈为空,说明字符串不满足条件
if(stk.top() == s[i]-1 || stk.top() == s[i]-2){ // 使用ASCII码来判断当前栈中是否为其对应的左括号
stk.pop(); // 如果是对应的左括号则出栈,并继续循环
continue;
}
else return false; // 如果不是对应的左括号,则直接返回false
}
}
if(!stk.empty()) return false; // 当遍历结束,但栈中还剩余有未出栈匹配的左括号时,说明不满足条件
return true; // 以上条件都满足,则返回true
}
};

上面代码只对字符串进行了一次扫描,时间复杂度为\(O(n)\).

Leecode 1047. 删除字符串中的所有相邻重复项

题目描述

给出由小写字母组成的字符串 s,重复项删除操作会选择两个相邻且相同的字母,并删除它们。

s 上反复执行重复项删除操作,直到无法继续删除。

在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。

  • 示例:

输入:"abbaca"

输出:"ca"

解释:

例如,在 "abbaca" 中,我们可以删除 "bb" 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 "aaca",其中又只有 "aa" 可以执行重复项删除操作,所以最后的字符串为 "ca"

解题思路与代码展示

本题要求删除字符串中相邻的重复项,其中包括删除后相邻的情况。本题同样是考虑使用一个栈来实现,逐个扫描字符串的同时,将当前字符与栈顶元素进行比较,如果两个元素相等,则将栈中元素出栈(相当于删除两个重复项);如果栈中元素不同,则将当前元素入栈。这样逻辑处理完整个字符串之后,再将栈中的字符逐个出栈并进行一次翻转,最后即可得到删去重复项后的字符串。

具体代码实现如下

class Solution {
public:
string removeDuplicates(string s) {
stack<char> stk1; // 定义用于判断删除元素的栈
for(int i = 0; i < s.size(); i++){ // 逐个扫描字符串中的字符
if(stk1.empty() || stk1.top() != s[i]) stk1.push(s[i]); // 如果栈顶元素和当前元素不相等,则入栈(需要先判断如果栈为空也需要入栈)
else stk1.pop(); // 如果栈不空,且栈顶元素和当前元素相等,则需要将栈顶元素出栈,相当于删除
}
stack<char> stk2; // 定义用于翻转字符串的栈
while(!stk1.empty()){ // 将删除元素后的栈中的元素逐个压栈到第二个栈中
stk2.push(stk1.top());
stk1.pop();
}
s = ""; // 初始化输出字符串
while(!stk2.empty()){ // 将第二个栈中的字符逐个出栈并连接到输出字符串上
s += stk2.top();
stk2.pop();
}
return s; // 返回输出最终结果
}
};

上面代码的时间复杂度为\(O(n)\),空间复杂度为\(O(n)\)。

今日总结

今天复习了栈和队列这两种基本数据类型,而且感觉今天题目都不算难,没啥好复盘的。。

代码随想录第十天 | Leecode 232. 用栈实现队列、Leecode 225. 用队列实现栈、 Leecode 20. 有效的括号、Leecode 1047. 删除字符串中的所有相邻重复项的更多相关文章

  1. 代码随想录算法训练营day11 | leetcode 20. 有效的括号 1047. 删除字符串中的所有相邻重复项 150. 逆波兰表达式求值

    基础知识 String StringBuilder 操作 public class StringOperation { int startIndex; int endIndex; { //初始容量为1 ...

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

    基础知识 使用ArrayDeque 实现栈和队列 stack push pop peek isEmpty() size() queue offer poll peek isEmpty() size() ...

  3. x264代码剖析(十五):核心算法之宏块编码中的变换编码

    x264代码剖析(十五):核心算法之宏块编码中的变换编码 为了进一步节省图像的传输码率.须要对图像进行压缩,通常採用变换编码及量化来消除图像中的相关性以降低图像编码的动态范围.本文主要介绍变换编码的相 ...

  4. WebShell代码分析溯源(十)

    WebShell代码分析溯源(十) 一.一句话变形马样本 <?php $e = $_REQUEST['e'];register_shutdown_function($e, $_REQUEST[' ...

  5. 代码随想录第十三天 | 150. 逆波兰表达式求值、239. 滑动窗口最大值、347.前 K 个高频元素

    第一题150. 逆波兰表达式求值 根据 逆波兰表示法,求表达式的值. 有效的算符包括 +.-.*./ .每个运算对象可以是整数,也可以是另一个逆波兰表达式. 注意 两个整数之间的除法只保留整数部分. ...

  6. 代码随想录第八天 |344.反转字符串 、541. 反转字符串II、剑指Offer 05.替换空格 、151.翻转字符串里的单词 、剑指Offer58-II.左旋转字符串

    第一题344.反转字符串 编写一个函数,其作用是将输入的字符串反转过来.输入字符串以字符数组 s 的形式给出. 不要给另外的数组分配额外的空间,你必须原地修改输入数组.使用 O(1) 的额外空间解决这 ...

  7. 代码随想录-day1

    链表 今天主要是把链表专题刷完了,链表专题的题目不是很难,基本都是考察对链表的操作的理解. 在处理链表问题的时候,我们通常会引入一个哨兵节点(dummy),dummy节点指向原链表的头结点.这样,当我 ...

  8. 代码随想录 day0 博客怎么写

    前言 2.25日开始记录自己的博客生涯以及代码随想录训练营的每日内容 一.题目链接怎么找?怎么设置连接? 力扣题目链接1:力扣 二.正文怎么写? 二分查找 算法思路: 二分查找需要保证数组为有序数组同 ...

  9. 【LeetCode动态规划#05】背包问题的理论分析(基于代码随想录的个人理解,多图)

    背包问题 问题描述 背包问题是一系列问题的统称,具体包括:01背包.完全背包.多重背包.分组背包等(仅需掌握前两种,后面的为竞赛级题目) 下面来研究01背包 实际上即使是最经典的01背包,也不会直接出 ...

  10. 代码随想录-day2

    哈希表 基础知识 哈希表和链表都是属于基础数据结构的一种,都是必须掌握牢靠的知识. 哈希表是根据关键码的值而直接进行访问的数据结构. 简单来说就是使用数据得到的哈希值来作为哈希表的key用于获取数据. ...

随机推荐

  1. FLink16--计数窗口--CountWindiwApp

    一.依赖 https://www.cnblogs.com/robots2/p/16048648.html 二.代码 概念:窗口来多少条计算一次,存在滚动和滑动两种情况 package net.xdcl ...

  2. Luogu P9646 SNCPC2019 Paper-cutting 题解 [ 紫 ] [ manacher ] [ 贪心 ] [ 哈希 ] [ BFS ]

    Paper-cutting:思维很好,但代码很构式的 manacher 题. 蒟蒻 2025 年切的第一道题,是个紫,并且基本独立想出的,特此纪念. 判断能否折叠 我们先考虑一部分能折叠需要满足什么条 ...

  3. 解决easyexcel合并单元格数组求和重复问题

    背景 EasyExcel(根据条件动态合并单元格的重复数据))_Violet-CSDN博客_easyexcel动态合并单元格现有的订单导出是使用的easyExcel完成的.对于相同单元格的合并是自定义 ...

  4. 【BUUCTF】HardSQL

    [BUUCTF]HardSQL 题目来源 收录于:BUUCTF 极客大挑战 2019 题目描述 一道纯粹的SQL注入题 尝试进行注入,发现对以下字符进行了过滤: = %20(空格) %09 %0a % ...

  5. C# 将list进行随机排序

    private List<T> RandomSortList<T>(List<T> ListT) { Random random = new Random(); L ...

  6. C# async/await使用举例

    1.async/await几点总结 a.被async标记的方法,返回值类型只能为void.Task.Task<T>. b.被async标记的方法,内部可以有await修饰符,表明内部逻辑某 ...

  7. python 二级 语言基本元素笔记-字符串

    l='12345' 1.递增顺序: 正向递增从0开始 负向从[-1]开始,l[1]=2,l[-1]=5 2.切片操作:左开右闭,l[2:5]=3,4 3.导入库,引入 库名.函数名 input函数 输 ...

  8. FastAPI 错误处理与自定义错误消息完全指南:构建健壮的 API 应用 🛠️

    title: FastAPI 错误处理与自定义错误消息完全指南:构建健壮的 API 应用 ️ date: 2025/3/12 updated: 2025/3/12 author: cmdragon e ...

  9. AI编程:最疯狂的MCP服务器你一定要试试

    我还记得我第一次听说MCP(模型上下文协议)的时候,我心想: "哈?又一个花里胡哨的缩写,这个世界已经快被这些缩写淹没了!" 但当我意识到MCP就像AI界的通用连接器--就像USB ...

  10. postgresql 查询表结构

    sql查询 SELECT A.attnum, ( SELECT description FROM pg_catalog.pg_description WHERE objoid = A.attrelid ...