代码随想录 栈与队列

232.用栈实现队列

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(双端队列)来模拟一个栈,只要是标准的栈操作即可。
import java.util.Deque;
import java.util.LinkedList;class MyQueue {private Deque<Integer> stackIn;  // 输入栈,用于入队操作private Deque<Integer> stackOut; // 输出栈,用于出队和获取队首元素操作public MyQueue() {this.stackIn = new LinkedList<Integer>();this.stackOut = new LinkedList<Integer>();}// 将元素推入输入栈public void push(int x) {stackIn.push(x);}// 从队列中弹出元素public int pop() {unload(); // 确保输出栈不为空return stackOut.pop();}// 获取队列首部的元素public int peek() {unload(); // 确保输出栈不为空return stackOut.peek();}// 检查队列是否为空public boolean empty() {if(stackIn.isEmpty() && stackOut.isEmpty()){return true;}return false;}// 从输入栈向输出栈转移元素private void unload(){if(!stackOut.isEmpty()){return; // 如果输出栈不为空,无需转移}// 当输出栈为空时,将输入栈的元素逐个弹出并压入输出栈while (!stackIn.isEmpty()) {stackOut.push(stackIn.pop());}}
}/*** 您的 MyQueue 对象将被实例化并按如下方式调用:* MyQueue obj = new MyQueue();* obj.push(x);* int param_2 = obj.pop();* int param_3 = obj.peek();* boolean param_4 = obj.empty();*/

上述代码的主要思路是将元素从输入栈中转移到输出栈中时将元素的顺序颠倒,此时再从输出栈中pop或者peek元素时的顺序就是队列的先入先出的顺序。

 225.用队列实现栈

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(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。
import java.util.Queue;
import java.util.LinkedList;class MyStack {Queue<Integer> first; // 第一个队列Queue<Integer> second; // 第二个队列public MyStack() {first = new LinkedList<>(); // 初始化第一个队列second = new LinkedList<>(); // 初始化第二个队列}// 将元素推入栈顶public void push(int x) {first.offer(x); // 将元素添加到第一个队列中}// 弹出栈顶元素public int pop() {// 如果第一个队列不为空,则将其除了最后一个元素外的所有元素转移到第二个队列中if(first.isEmpty()){Queue<Integer> temp = first;first = second;second = temp;}int size = first.size();for(int i = 0; i < size - 1; i ++){second.offer(first.poll());}return first.poll(); // 返回第一个队列的最后一个元素(即栈顶元素)}// 获取栈顶元素public int top() {if(first.isEmpty()){Queue<Integer> temp = first;first = second;second = temp;}int size = first.size();for(int i = 0; i < size - 1; i ++){second.offer(first.poll());}return first.peek(); // 返回第一个队列的最后一个元素(即栈顶元素),但不移除}// 检查栈是否为空public boolean empty() {if(first.isEmpty() && second.isEmpty()){return true;}return false;}
}/*** 您的 MyStack 对象将被实例化并按如下方式调用:* MyStack obj = new MyStack();* obj.push(x);* int param_2 = obj.pop();* int param_3 = obj.top();* boolean param_4 = obj.empty();*/

上述代码的主要思路是元素从第一个队列转移到第二个队列,取第一个队列的第一个元素,此时元素的顺序存在第二个队列中是没有改变的,每次进行取出操作时将非空的数组当做第一个队列

20.有效的括号

20. 有效的括号

简单

提示

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

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。
  3. 每个右括号都有一个对应的相同类型的左括号。
import java.util.Deque;
import java.util.LinkedList;class Solution {public boolean isValid(String s) {Deque<Character> deque = new LinkedList<>(); // 使用双端队列来存储左括号for(int i = 0; i < s.length(); i++){char sChar = s.charAt(i);// 如果是左括号,则将对应的右括号入栈if(sChar == '('){deque.push(')');}else if(sChar == '{'){deque.push('}');}else if(sChar == '['){deque.push(']');}// 如果是右括号,但栈为空或栈顶元素不匹配当前右括号,则返回falseelse if(deque.isEmpty() || deque.peek() != sChar){return false;}// 如果是右括号且与栈顶元素匹配,则将栈顶元素出栈else{deque.pop();}}// 如果栈不为空,则说明左括号多于右括号,返回falseif(!deque.isEmpty()){return false;}return true; // 栈为空,表示所有括号都匹配,返回true}
}

主要的思路是每遇到一个左括号就放一个与他对应的右括号到栈中,每遇到一个右括号就去栈中找最新一个放进去的右括号匹配,如果匹配就从栈中移除一个,不匹配则失败。如果最后栈中还有右括号没有被匹配掉,就失败

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

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

简单

提示

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

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

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

示例:

输入:"abbaca"
输出:"ca"
解释:
例如,在 "abbaca" 中,我们可以删除 "bb" 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 "aaca",其中又只有 "aa" 可以执行重复项删除操作,所以最后的字符串为 "ca"。
import java.util.Deque;
import java.util.LinkedList;class Solution {public String removeDuplicates(String s) {// 使用一个栈来存储字符Deque<Character> stack = new LinkedList<>();// 遍历输入字符串for(int i = 0; i < s.length(); i++){// 如果栈不为空并且当前字符与栈顶字符相同if(!stack.isEmpty() && stack.peek() == s.charAt(i)){// 移除栈顶字符stack.pop();} else {// 将当前字符压入栈中stack.push(s.charAt(i));}}// 使用 StringBuilder 构建结果字符串StringBuilder builder = new StringBuilder();// 将栈中字符出栈并添加到字符串构建器中while(!stack.isEmpty()){builder.append(stack.pop());}// 反转字符串构建器中的内容builder.reverse();// 返回去除重复字符后的结果字符串return builder.toString();}
}

本质上是匹配问题

150.逆波兰表达式

150. 逆波兰表达式求值

中等

给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。

请你计算该表达式。返回一个表示表达式值的整数。

注意:

  • 有效的算符为 '+''-''*' 和 '/' 。
  • 每个操作数(运算对象)都可以是一个整数或者另一个表达式。
  • 两个整数之间的除法总是 向零截断 。
  • 表达式中不含除零运算。
  • 输入是一个根据逆波兰表示法表示的算术表达式。
  • 答案及所有中间计算结果可以用 32 位 整数表示。

示例 1:

输入:tokens = ["2","1","+","3","*"]
输出:9
解释:该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9

示例 2:

输入:tokens = ["4","13","5","/","+"]
输出:6
解释:该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6

示例 3:

输入:tokens = ["10","6","9","3","+","-11","*","/","*","17","+","5","+"]
输出:22
解释:该算式转化为常见的中缀算术表达式为:((10 * (6 / ((9 + 3) * -11))) + 17) + 5
= ((10 * (6 / (12 * -11))) + 17) + 5
= ((10 * (6 / -132)) + 17) + 5
= ((10 * 0) + 17) + 5
= (0 + 17) + 5
= 17 + 5
= 22

提示:

  • 1 <= tokens.length <= 104
  • tokens[i] 是一个算符("+""-""*" 或 "/"),或是在范围 [-200, 200] 内的一个整数
import java.util.Deque;
import java.util.LinkedList;class Solution {// 计算逆波兰表达式public int evalRPN(String[] tokens) {// 使用栈存储操作数Deque<Integer> stack = new LinkedList<Integer>();int n = tokens.length;// 遍历逆波兰表达式的每个元素for (int i = 0; i < n; i++) {String token = tokens[i];// 如果是数字,则压入栈中if (isNumber(token)) {stack.push(Integer.parseInt(token));} else {// 如果是运算符,则取出栈顶的两个操作数进行计算,并将结果压入栈中int num2 = stack.pop();int num1 = stack.pop();switch (token) {case "+":stack.push(num1 + num2);break;case "-":stack.push(num1 - num2);break;case "*":stack.push(num1 * num2);break;case "/":stack.push(num1 / num2);break;default:// 对于无效的运算符,不做任何操作}}}// 返回栈顶元素,即为最终计算结果return stack.pop();}// 判断字符串是否为数字public boolean isNumber(String token) {// 如果不是加减乘除运算符,则认为是数字return !("+".equals(token) || "-".equals(token) || "*".equals(token) || "/".equals(token));}
}

难点在于什么是逆波兰表达式,代码思路很好理解

栈的最后表演! | LeetCode:150. 逆波兰表达式求值_哔哩哔哩_bilibili

239.滑动窗口最大值

239. 滑动窗口最大值

困难

提示

给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

返回 滑动窗口中的最大值 

示例 1:

输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
滑动窗口的位置                最大值
---------------               -----
[1  3  -1] -3  5  3  6  7       31 [3  -1  -3] 5  3  6  7       31  3 [-1  -3  5] 3  6  7       51  3  -1 [-3  5  3] 6  7       51  3  -1  -3 [5  3  6] 7       61  3  -1  -3  5 [3  6  7]      7

示例 2:

输入:nums = [1], k = 1
输出:[1]

提示:

  • 1 <= nums.length <= 105
  • -104 <= nums[i] <= 104
  • 1 <= k <= nums.length

注意这里的提示k的范围

暴力解法,通过40/51,超时

class Solution {// 滑动窗口的最大值public int[] maxSlidingWindow(int[] nums, int k) {int n = nums.length;// 初始化输出数组的长度int [] output = new int[n - k + 1];// 遍历数组,计算滑动窗口的最大值for (int i = 0; i < n - k + 1; i++) {// 初始化当前窗口的最大值为整数最小值int max = Integer.MIN_VALUE;// 遍历当前窗口内的元素,寻找最大值for(int j = i; j < i + k; j++) {max = Math.max(max, nums[j]);}// 将当前窗口的最大值存入输出数组output[i] = max;}// 返回结果数组return output;}
}
class MyQueue {Deque<Integer> deque = new LinkedList<>();//弹出元素时,比较当前要弹出的数值是否等于队列出口的数值,如果相等则弹出//同时判断队列当前是否为空void poll(int val) {if (!deque.isEmpty() && val == deque.peek()) {deque.poll();}}//添加元素时,如果要添加的元素大于入口处的元素,就将入口元素弹出//保证队列元素单调递减//比如此时队列元素3,1,2将要入队,比1大,所以1弹出,此时队列:3,2void add(int val) {while (!deque.isEmpty() && val > deque.getLast()) {deque.removeLast();}deque.add(val);}//队列队顶元素始终为最大值int peek() {return deque.peek();}
}class Solution {public int[] maxSlidingWindow(int[] nums, int k) {if (nums.length == 1) {return nums;}int len = nums.length - k + 1;//存放结果元素的数组int[] res = new int[len];int num = 0;//自定义队列MyQueue myQueue = new MyQueue();//先将前k的元素放入队列for (int i = 0; i < k; i++) {myQueue.add(nums[i]);}res[num++] = myQueue.peek();for (int i = k; i < nums.length; i++) {//滑动窗口移除最前面的元素,移除是判断该元素是否放入队列myQueue.poll(nums[i - k]);//滑动窗口加入最后面的元素myQueue.add(nums[i]);//记录对应的最大值res[num++] = myQueue.peek();}return res;}
}

239. 滑动窗口最大值

困难

提示

给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

返回 滑动窗口中的最大值 

示例 1:

输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
滑动窗口的位置                最大值
---------------               -----
[1  3  -1] -3  5  3  6  7       31 [3  -1  -3] 5  3  6  7       31  3 [-1  -3  5] 3  6  7       51  3  -1 [-3  5  3] 6  7       51  3  -1  -3 [5  3  6] 7       61  3  -1  -3  5 [3  6  7]      7

示例 2:

输入:nums = [1], k = 1
输出:[1]

提示:

  • 1 <= nums.length <= 105
  • -104 <= nums[i] <= 104
  • 1 <= k <= nums.length
class Solution {public int[] topKFrequent(int[] nums, int k) {// 统计每个数字出现的频率Map<Integer,Integer> map = new HashMap<>();for(int i = 0; i < nums.length; i++){map.put(nums[i], map.getOrDefault(nums[i], 0) + 1);}// 创建一个大顶堆,按照出现频率排序Queue<int[]> queue = new PriorityQueue<>((m, n) -> n[1] - m[1]);// 将每个数字和其频率加入堆中for(Map.Entry<Integer,Integer> entry : map.entrySet()){queue.add(new int[]{entry.getKey(), entry.getValue()});}// 从堆中弹出前k个高频数字int[] ans = new int[k];for(int i = 0; i < k; i++){ans[i] = queue.poll()[0];}return ans;}
}

Java中的队列和栈-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/692176.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

js中对象的属性要注意的点以及在vue中watch对象的属性的方法

取对象值有两种方式&#xff0c; const obj{ a:1 } obj.a或者obj[a],中括号还可以写成 const name a obj[name]和obj[a]是一个意思。 然后在vue的watch要监听对象的属性&#xff0c;写法是 watch:{ obj.a(new,old){} } 这样的方式。 然后对象的深度拷贝可以通过自…

FIDO2入门以及相关概念 Client to Authenticator Protocol

​ 本文根据官方文档的定义以及我疑惑的问题做出的相关整理的问答&#xff0c;可能会有偏差&#xff0c;请以官网为准。 官网文档网址&#xff1a;Client to Authenticator Protocol (CTAP) ​ FIDO是什么 FIDO&#xff08;Fast Identity Online&#xff09;是一组开放标准和…

服务器遭受 DDoS 攻击的常见迹象有哪些?

服务器遭受 DDoS 攻击的现象很常见&#xff0c;并且有时不容易预防&#xff0c;有部分原因是它们的形式多种多样&#xff0c;而且黑客手段越来越隐蔽。如果您怀疑自己可能遭受 DDoS 攻击&#xff0c;可以寻找多种迹象。以下是 DDoS 攻击的5个常见迹象&#xff1a; 1.网络流量无…

虚拟机+麒麟海光+达梦数据库linux 安装教程

一 下载 虚拟机下载地址下载 VMware Workstation Pro | CN 达梦数据库下载地址 产品下载 | 达梦数据库 (dameng.com) 银河麒麟下载地址 国产操作系统、银河麒麟、中标麒麟、开放麒麟、星光麒麟——麒麟软件官方网站 (kylinos.cn) 二 安装 虚拟机安装 https://www.cnblogs…

每日一练:前端js实现算法之整数反转

方法一:使用字符串反转 function reverseInt(num) {const reversed = parseInt(num.toString().split().reverse

leetcode3043. 最长公共前缀的长度

给你两个 正整数 数组 arr1 和 arr2 。 正整数的 前缀 是其 最左边 的一位或多位数字组成的整数。例如&#xff0c;123 是整数 12345 的前缀&#xff0c;而 234 不是 。 设若整数 c 是整数 a 和 b 的 公共前缀 &#xff0c;那么 c 需要同时是 a 和 b 的前缀。例如&#xff0c…

Haproxy基础概念

1.简介 HAProxy&#xff0c;它可以提供高可用性、负载均衡&#xff0c;以及基于TCP(第四层)和HTTP&#xff08;第七层&#xff09;的应用程序代理。 HAProxy特别适用于那些负载特大的web站点&#xff0c;这些站点通常又需要会话保持或七层处理。HAProxy运行在当前的硬件上&…

python+selenium 定位到元素,无法点击的解决方法

今天小编就为大家分享一篇pythonselenium 定位到元素,无法点击的解决方法&#xff0c;具有很好的参考价值&#xff0c;希望对大家有所帮助。一起跟随小编过来看看吧 selenium.common.exceptions.WebDriverException: Message: Element is not clickable at point (234.75, 22)…

【JavaScript 漫游】【017】异步操作概述

文章简介 本文为【JavaScript 漫游】专栏的第 017 篇文章&#xff0c;主要记录了 ES5 规范中异步操作的基本知识点。 单线程模型同步任务和异步任务任务队列和事件循环异步操作的模式 单线程模型 单线程模型指的是&#xff0c;JS 只在一个线程上运行。它同时只能执行一个任…

Mysql如何优化数据查询方案

mysql做读写分离 读写分离是提高mysql并发的首选方案。 Mysql主从复制的原理 mysql的主从复制依赖于binlog&#xff0c;也就是记录mysql上的所有变化并以二进制的形式保存在磁盘上&#xff0c;复制的过程就是将binlog中的数据从主库传输到从库上。 主从复制过程详细分为3个阶段…

每日OJ题_二叉树dfs②_力扣129. 求根节点到叶节点数字之和

目录 力扣129. 求根节点到叶节点数字之和 解析代码 力扣129. 求根节点到叶节点数字之和 129. 求根节点到叶节点数字之和 难度 中等 给你一个二叉树的根节点 root &#xff0c;树中每个节点都存放有一个 0 到 9 之间的数字。 每条从根节点到叶节点的路径都代表一个数字&am…

基于Windows搭建ftp服务器

WinR搜索’服务器管理器’,配置–用户和组 创建用户和组&#xff0c;将用户添加到组里 按图示创建一个文件&#xff0c;右键属性–安全 将刚才创建的组添加到对象里&#xff0c;并赋予他读取和写入的权限 角色–添加角色 勾选web服务器IIS 搜索IIS–网站右键–添加FTP站点…

vivado Asymmetric RAMs

以下部分提供了非对称RAM的VHDL和Verilog编码示例。 读比写宽时的简单双端口非对称RAM&#xff08;VHDL&#xff09; Filename: asym_ram_sdp_read_wider.vhd -- Asymmetric port RAM -- Read Wider than Write -- asym_ram_sdp_read_wider.vhd library ieee; use ieee.s…

【软考中级备考笔记】计算机体系结构

计算机体系结构 2月19日 – 天气&#xff1a;阴转小雪 1. 冯诺依曼计算机体系结构 冯诺依曼将计算机分为了五大部分&#xff0c;分别是&#xff1a; 控制器&#xff1a;主要负责协调指令到执行运算器&#xff1a;负责算数和逻辑运算存储器&#xff1a;负责存储在指令执行过程…

全网最 2024 GitHub Copilot超详细免费激活教学-干货

全网最&#x1f525; 2024 GitHub Copilot免费超详细激活教学 尊重原创&#xff0c;编写不易 &#xff0c;帮忙点赞关注一下~转载小伙伴请注明出处&#xff01;谢谢 GitHub Copilot 概述 GitHub Copilot 是由 GitHub 和 OpenAI 合作开发的一款人工智能编程助手。它利用机器…

JS基础(语法结构变量数据类型运算符流程控制)

JS基础(语法结构/变量/数据类型/运算符/流程控制) 目录 JS基础(语法结构/变量/数据类型/运算符/流程控制)什么是js&#xff1f;注释语法语法结构引入方式【1】script标签内部直接书写js代码【2】script标签src属性引入外部js代码 JS基础数据类型变量与常量变量的定义常量的定义…

[office] Excel使用INTRATE函数计算债券的一次性付息利率 #职场发展#笔记

Excel使用INTRATE函数计算债券的一次性付息利率 在Excel中&#xff0c;如果计算债券的一次性付息利率&#xff0c;可以使用INTRATE函数计算债券的一次性付息利率。Excel2007可使用INTRATE函数计算债券的一次性付息利率。 如上图所示&#xff0c;在B7单元格输入公式&#xff1…

ONLYOFFICE 8.0:引领数字化办公新纪元

目录 前言 软件安装 软件启动 软件新版本特性 个人评价 总结 前言 在当今快节奏的数字化世界中&#xff0c;高效的办公软件已成为企业竞争力的关键因素。ONLYOFFICE&#xff0c;作为全球领先的办公解决方案提供商&#xff0c;始终致力于通过技术创新来优化用户体验。如今…

Java使用Redis实现消息队列

近期刷Java面试题刷到了“如何使用Redis实现消息队列”&#xff0c;解答如下&#xff1a; 一般使用 list 结构作为队列&#xff0c; rpush 生产消息&#xff0c; lpop 消费消息。当 lpop 没有消息的时候&#xff0c;要适当sleep 一会再重试。若不使用sleep&#xff0c;则可以用…

习题2.3 old bill

描述 Among grandfather’s papers a bill was found. 72 turkeys $679 The first and the last digits of the number that obviously represented the total price of those turkeys are replaced here by blanks (denoted _), for they are faded and are illegible. What a…