LeetCode——栈和队列(Java)

栈和队列

  • 简介
  • [简单] 232. 用栈实现队列
  • [简单] 225. 用队列实现栈
  • [简单] 20. 有效的括号
  • [简单] 1047. 删除字符串中的所有相邻重复项
  • [中等] 150. 逆波兰表达式求值
  • [困难] 239. 滑动窗口最大值
  • [中等] 347. 前 K 个高频元素

简介

记录一下自己刷题的历程以及代码。写题过程中参考了 代码随想录。会附上一些个人的思路,如果有错误,可以在评论区提醒一下。

涉及到:栈、队列、双端队列、map、优先队列、java装箱拆箱问题。

[简单] 232. 用栈实现队列

原题链接

使用两个栈实现,stack1接受数据,每次要pop或者peek的时候,把stack1里的数据再出栈入栈 放置到stack2中,这样又对stack1中的数据做了一次转置。注意stack2中有元素时,stack1不能向stack2传入数据,否则会出现顺序错乱。

class MyQueue {
    //假设了所有操作都是有效的
    public Stack<Integer> stack1;
    public Stack<Integer> stack2;
    public MyQueue() {
        stack1 = new Stack<>();
        stack2 = new Stack<>();
    }

    public void push(int x) {
        stack1.push(x);
    }

    public int pop() {
        reverse();
        return stack2.pop();
    }

    public int peek() {
        reverse();
        return stack2.peek();
    }

    public boolean empty() {
        if(stack2.empty() && stack1.empty()){
            return true;
        }
        return false;
    }
    //stack2中没有元素时,把stack1中元素全部转置
    private void reverse(){
        if(stack2.empty()) {
            while (!stack1.empty()) {
                Integer temp = stack1.pop();
                stack2.push(temp);
            }
        }
    }
}

[简单] 225. 用队列实现栈

原题链接

使用两个队列实现,时刻保持只有一个队列A存放元素,另一个队列B用于pop或者top操作时接收A的数据,就可以对队列A队尾的元素进行操作。队列A和队列B是相对概念,两个队列某一时刻都可能是存放元素的那个队列。

class MyStack {

    Queue<Integer> queue1;
    Queue<Integer> queue2;
    public MyStack() {
        queue1 = new LinkedList<Integer>();
        queue2 = new LinkedList<Integer>();
    }

    public void push(int x) {
        if(queue1.isEmpty()) queue2.add(x);
        else queue1.add(x);
    }

    public int pop() {
        if(queue1.isEmpty()) {
            while(queue2.size() > 1){
                queue1.add(queue2.poll());
            }
            return queue2.poll();
        }
        while(queue1.size() > 1){
            queue2.add(queue1.poll());
        }
        return queue1.poll();
    }

    public int top() {
        if(queue1.isEmpty()) {
            while(queue2.size() > 1){
                queue1.add(queue2.poll());
            }
            Integer temp =  queue2.peek();
            queue1.add(queue2.poll());
            return temp;
        }
        while(queue1.size() > 1){
            queue2.add(queue1.poll());
        }
        Integer temp =  queue1.peek();
        queue2.add(queue1.poll());
        return temp;
    }

    public boolean empty() {
        if(queue1.isEmpty() && queue2.isEmpty()){
            return true;
        }
        return false;
    }
}

[简单] 20. 有效的括号

原题链接

使用栈做符号匹配,碰到左括号压栈,碰到右括号,看目前栈顶是否与之匹配,若不匹配或空,则表示匹配错误。若循环结束栈不为空,表示有多余的左括号。

class Solution {
    public boolean isValid(String s) {
        Stack<Character> stack = new Stack<>();
        for(int i = 0; i < s.length(); i++){
            if(s.charAt(i) == '[' || s.charAt(i) == '{' || s.charAt(i) == '('){
                stack.push(s.charAt(i));
            }else if(s.charAt(i) == ']'){
                if(stack.empty() || stack.peek() != '[') return false;
                stack.pop();
            }else if(s.charAt(i) == '}'){
                if(stack.empty() || stack.peek() != '{') return false;
                stack.pop();
            }else if(s.charAt(i) == ')'){
                if(stack.empty() || stack.peek() != '(') return false;
                stack.pop();
            }
        }
        if(stack.empty()) return true;
        return false;
    }
}

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

原题链接

方法①:使用队列,每次入栈时如果与栈顶元素相同,则不入栈,并弹出栈顶元素。

class Solution {
    public String removeDuplicates(String s) {
        ArrayDeque<Character> stack = new ArrayDeque<>();
        for(int i = 0; i < s.length(); i++){
            if(!stack.isEmpty() && stack.peek() == s.charAt(i)){
                stack.pop();
            }else{
                stack.push(s.charAt(i));
            }
        }
        String str = "";
        //剩余的元素即为不重复的元素
        while (!stack.isEmpty()) {
            str = stack.pop() + str;
        }
        return str;
    }
}

方法②:快慢指针法指针法,就把[0-slow]范围内看作一个栈,栈顶是slow指针的位置,一旦出现c[slow] == c[slow - 1],就回退一次,将栈顶弹出,否则就将当前fast遍历到的元素加进来。

class Solution {
    //快慢指针法
    public String removeDuplicates(String s) {
        //声明字符串数组用于修改,String类是静态变量
        char[] c = s.toCharArray();
        int slow = 0;
        int fast = 0;
        while(fast < c.length){
            c[slow] = c[fast];
            if(slow > 0 && c[slow] == c[slow - 1]) {
                slow--;
            } else {
                slow++;
            }
            fast++;
        }
        return new String(c, 0, slow);
    }
}

[中等] 150. 逆波兰表达式求值

原题链接

token是数字,就做类型转换压入栈,如果是运算符,弹出栈顶两个数字做运算,记住减法和除法是有顺序的。

class Solution {
    public int evalRPN(String[] tokens) {
        ArrayDeque<Integer> stack = new ArrayDeque<>();
        for(int i = 0; i < tokens.length; i++){
            if(tokens[i].equals("+")){
                int temp1 = stack.pop();
                int temp2 = stack.pop();
                stack.push(temp1 + temp2);
            }else if(tokens[i].equals("-")){
                int temp1 = stack.pop();
                int temp2 = stack.pop();
                stack.push(temp2 - temp1);
            }else if(tokens[i].equals("*")){
                int temp1 = stack.pop();
                int temp2 = stack.pop();
                stack.push(temp1 * temp2);
            }else if(tokens[i].equals("/")){
                int temp1 = stack.pop();
                int temp2 = stack.pop();
                stack.push(temp2 / temp1);
            }else{
                stack.push(Integer.parseInt(tokens[i]));
            }
        }
        return stack.pop();
    }
}

[困难] 239. 滑动窗口最大值

原题链接

原先pop方法和push方法都是Integer参数,一半示例无法通过,改成int之后顺利通过。

涉及到装箱拆箱问题,==运算符可以应用与对象包装器对象,只不过检测的事对象是否指向同一个存储区域。比如Integer a = 1000;Integer b =1000a==b 未必是true。

缓存机制:Java 基本数据类型的包装类型的大部分都用到了缓存机制来提升性能。Byte,Short,Integer,Long 这 4 种包装类默认创建了数值 [-128,127] 的相应类型的缓存数据
在这里插入图片描述

class MoQueue{
    public ArrayDeque<Integer> queue;
    public MoQueue(){
        queue = new ArrayDeque<Integer>();
    }
    public void pop(int a){
        if(!queue.isEmpty() && queue.peek() == a)
            queue.pollFirst();
        return;
    }
    public void push(int a){
        while(!queue.isEmpty() && a > queue.getLast()){
            queue.pollLast();
        }
        queue.addLast(a);
    }
    public Integer peek(){
        return queue.peek();
    }
}
class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        MoQueue moQueue = new MoQueue();
        int[] answer = new int[nums.length - k + 1];
        for(int i = 0; i < k; i++){
            moQueue .push(nums[i]);
        }
        //放入第一个窗口最大值
        answer[0] = moQueue.peek();
        for(int i = k; i < nums.length; i++){
            moQueue.pop(nums[i - k]);
            moQueue.push(nums[i]);
            answer[i - k + 1] = moQueue.peek();
        }
        return answer;
    }
}

[中等] 347. 前 K 个高频元素

原题链接

使用map存储键值对记录每个数字出现的频次,再使用优先队列定义排序,获取前k个队头元素即可。

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        Map<Integer,Integer> map = new HashMap<>();//key为数组元素值,val为对应出现次数
        for(int num:nums){
            map.put(num,map.getOrDefault(num,0)+1);
        }
        PriorityQueue<Integer> pq = new PriorityQueue<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer a, Integer b) {
                return map.get(b) - map.get(a);
            }
        });
        int[] ans = new int[k];
        int i = 0;
        for(Integer key : map.keySet()){
            pq.add(key);
        }
        while(i < k){
            ans[i++] = pq.remove();
        }
        return ans;
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Linux】进程优先级以及Linux内核进程调度队列的简要介绍

进程优先级 基本概念查看系统进程修改进程的优先级Linux2.6内核进程调度队列的简要介绍和进程优先级有关的概念进程切换 基本概念 为什么会存在进程优先级&#xff1f;   进程优先级用于确定在资源竞争的情况下&#xff0c;哪个进程将被操作系统调度为下一个运行的进程。进程…

Linux设备模型(七) - Netlink

一&#xff0c;什么是netlink通信机制 Netlink套接字是用以实现用户进程与内核进程通信的一种特殊的进程间通信(IPC) ,也是网络应用程序与内核通信的最常用的接口。Netlink 是一种特殊的 socket&#xff0c;它是 Linux 所特有的。 Netlink 是一种在内核与用户应用间进行双向数…

PCB:多CAN口的信号转接板

背景 在测试多路CAN口时&#xff0c;需要频繁更换接口引脚&#xff0c;从而接入CAN收发器。为了提升测试效率&#xff0c;可以设计一个简易多路CAN收发器转接板。PCB板子一端是40脚母口&#xff0c;另一端是10路CAN螺钉式接线端子&#xff0c;自带电池减少接线。 分配空闲时间…

网络编程:基于TCP和UDP的服务器、客户端

1.基于TCP通信服务器 程序代码&#xff1a; 1 #include<myhead.h>2 #define SER_IP "192.168.126.121"//服务器IP3 #define SER_PORT 8888//服务器端口号4 int main(int argc, const char *argv[])5 {6 //1.创建用于监听的套接字7 int sfd-1;8 sf…

Sora:开启视频生成新时代的强大人工智能模型

目录 一、Sora模型的诞生与意义 二、Sora模型的技术特点与创新 三、Sora模型的应用前景与影响 四、面临的挑战与未来发展 1、技术挑战 2、道德和伦理问题 3、计算资源需求 4、未来发展方向 随着信息技术的飞速发展&#xff0c;人工智能&#xff08;AI&#xff09;已成为…

Unity(第九部)物体类

拿到物体的某些数据 using System.Collections; using System.Collections.Generic; using UnityEngine;public class game : MonoBehaviour {// Start is called before the first frame updatevoid Start(){//拿到当前脚本所挂载的游戏物体//GameObject go this.gameObject;…

Python算法100例-2.10 马克思手稿中的数学题

完整源代码项目地址&#xff0c;关注博主私信源代码后可获取 1.问题描述2.问题分析3.算法设计4.确定程序框架5.完整的程序6.运行结果 1&#xff0e;问题描述 马克思手稿中有一道趣味数学问题&#xff1a;有30个人&#xff0c;其中有男人、女人和小孩&#xff0c;他们在同一家…

C语言基础18 循环

们可能需要多次执行同一块代码。一般情况下&#xff0c;语句是按顺序执行的&#xff1a;函数中的第一个语句先执行&#xff0c;接着是第二个语句&#xff0c;依此类推。 编程语言提供了更为复杂执行路径的多种控制结构。 循环语句允许我们多次执行一个语句或语句组&#xff0…

小红书的几种赚钱方式解读

小红书的七种变现方式&#xff1a; 1.通过小红书蒲公英平台接广告&#xff0c;粉丝数量大于1000的用户可以开通。单条笔记的广告费用从几百元到几十万不等。 2.开设小红书专栏&#xff0c;粉丝数量大于1万的用户可以开通。 3.进行私域变现&#xff0c;将小红书的咨询引导到微信…

Java 小项目开发日记 03(文章分类接口的开发)

Java 小项目开发日记 03&#xff08;文章分类接口的开发&#xff09; 项目目录 配置文件&#xff08;pom.xml&#xff09; <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocat…

内核打印应用程序出错信息,DEBUG_USER

前言 在 Linux 系统中&#xff0c;运行一个应用程序&#xff0c;突然提示段错误&#xff0c;并停止运行 # ./crash.out Segmentation fault如果这个时候操作系统能多提示点错误信息&#xff0c;那将会缩短我们 debug 的时间。 core dump 就是一个办法&#xff0c;可以查看我…

javaWeb学习04

AOP核心概念: 连接点: JoinPoint, 可以被AOP控制的方法 通知: Advice 指哪些重复的逻辑&#xff0c;也就是共性功能(最终体现为一个方法) 切入点: PointCut, 匹配连接点的条件&#xff0c;通知仅会在切入点方法执行时被应用 目标对象: Target, 通知所应用的对象 通知类…

nginx(三)实现反向代理客户端 IP透传

正常情况下&#xff0c;客户端去访问代理服务器&#xff0c;然后代理服务器再取访问真实服务器&#xff0c;在真实服务器上&#xff0c;只能显示代理服务器的ip地址&#xff0c;而不显示客户端的ip地址&#xff0c;如果想让客户端的ip地址也能在真实服务端看见&#xff0c;这一…

数仓开发环境链接

这里写目录标题 1开发工具链接大数据组件1.1 启动hiveserver21.2配置DataGrip连接1.3测试使用 2 环境问题排查思路 1开发工具链接大数据组件 1.1 启动hiveserver2 数仓开发工具datagrip 需要用到JDBC协议链接到Hive&#xff0c;需要启动hiveserver2。 cd /opt/module/hive h…

string 类 经典习题之数字字符相加

题目&#xff1a; 给定两个字符串形式的非负整数 num1 和num2 &#xff0c;计算它们的和并同样以字符串形式返回。 你不能使用任何內建的用于处理大整数的库&#xff08;比如 BigInteger&#xff09;&#xff0c; 也不能直接将输入的字符串转换为整数形式。 题目来源&#xff1…

进程2月29日

题目&#xff1a;要求将当前路径下&#xff0c;所有文件的权限及最后一次的访问时间提取出来&#xff0c;写入到file.txt中。&#xff08;提示:opendir readir stat -->提取出来的数据写入到file.txt中&#xff09; 代码&#xff1a; #include <stdio.h> #include &…

C语言:数据在内存中的存储

C语言&#xff1a;数据在内存中的存储 整数存储原码、反码、补码转换规则数据与内存的关系 大小端字节序浮点数存储IEEE 754标准存储过程取用过程 数据的存储范围 整数存储 原码、反码、补码 整数的2进制表示方法有三种&#xff0c;即原码、反码和补码 三种表示方法均有符号位…

使用Python操作SQLite数据库

大家好&#xff0c;在数据涌现的今天&#xff0c;数据库已成为生活中不可或缺的工具。Python作为一种流行的编程语言&#xff0c;内置了多种用于操作数据库的库&#xff0c;其中之一就是SQLite。SQLite是一种轻量级的关系型数据库管理系统&#xff0c;它在Python中的应用非常广…

http模块学习

http模块 客户端&#xff1a;负责消费资源的电脑 服务器&#xff1a;负责对外提供网络资源的电脑&#xff0c;与普通电脑的区别就在于服务器上 安装了web服务器软件。 http模块是Node.js官方提供用来 创建web服务器的模块&#xff0c;通过http模块提供的http.createServer()方…

java之Bean对象

1. 什么是Bean&#xff1f; Bean被实例化的&#xff0c;是被Spring框架所管理的Java对象。 Spring容器会自动完成Bean的实例化。将所创建的的Bean自动注入到Ioc容器中以供调用。 spring框架中 IOC容器中管理的对象就是Bean对象 2. 第三方bean Bean 因为第三方bean&#xff0…