java算法day9

  • 232.用栈实现队列
    1. 用队列实现栈
    1. 有效的括号
    1. 删除字符串中的所有相邻重复项
    1. 逆波兰表达式求值

解决栈和队列的基本数据结构

Queue(队列)

在java中是一个接口。定义的方法:

//boolean add(E e): 将指定的元素插入此队列(如果立即可行且不会违反容量限制),在成功时返回 true,如果当前没有可用的空间,则抛出 IllegalStateException。
//E remove():获取并移除 此队列的 头 。
//E element() :获取 ,但是不移除此队列的 头 。

//boolean offer(E e):将指定的元素 插入 此队列(如果立即可行且不会违反容量限制),当使用有容量限制的队列时,此方法通常要优于 add(E),后者可能无法插入元素,而只是抛出一个异常。
//E poll():获取并移除 此队列的头,如果此队列为空,则返回 null。
//E peek(): 获取但不移除此队列的头;如果此队列为空,则返回 null。

在极端情况下,两组API的表现不一致。极端情况指的是 一组是抛异常,一组是返回特殊值

  • 插入的时候,队列满了
  • 删除或者获取的时候,队列空了。
    在这里插入图片描述

Deque

是个Queue的子接口,是java里面的双端队列。
Deque特点:

  1. Deque是Queue的子接口
  2. 数据结构表现:队列,栈,双端队列
  3. 存储元素有序
  4. 可存储重复元素
  5. 不能存储null(LinkedList除外)

Deque可以说非常的万能,能模拟很多数据结构,下面就是他能模拟的数据结构。

// ------------- 作为Queue的
//        E peek(): 获取队头元素,但不移除它
//        E poll():从队头移除元素
//        boolean offer(E e): 添加一个元素到 队尾

// ------------- 作为Stack的
//        E pop(): 从此列表所表示的堆栈处弹出一个元素。
//        void push(E e): 将元素推入此列表所表示的堆栈。

// ------------- 作为双端队列
//        boolean offerFirst(E e):  从 第一个位置 插入 指定元素
//        boolean offerLast(E e): 从 最后一个位置 插入 指定元素
//        E peekFirst(): 获取 但是不移除 第一个元素,如果列表为空,返回null
//        E peekLast(): 获取 但是不移除 最后一个元素,如果列表为空,返回null
//        E pollFirst(): 从 第一个位置 移除 元素
//        E pollLast(): 从 最后一个位置 移除 元素,如果列表为空,返回null

// -------------- 作为普通List的
//    boolean add(E e):将指定元素添加到此列表的结尾。
//    E remove():获取并移除此列表的头(第一个元素)。

//        void addFirst(E e): 将指定元素插入此列表的开头。
//        void addLast(E e): 将指定元素添加到此列表的结尾。
//        E getFirst(): 返回此列表的第一个元素。
//        E getLast(): 返回此列表的最后一个元素。
//        E removeFirst(): 移除并返回此列表的第一个元素。
//        E removeLast(): 移除并返回此列表的最后一个元素。

// 这个API,大家觉得应不应该出现在Deque这个接口里面。 
//        boolean removeFirstOccurrence(Object o): 从此列表中移除第一次出现的指定元素
//        boolean removeLastOccurrence(Object o): 从列表中移除最后一次出现的指定元素
//        Iterator<E> descendingIterator():获取一个倒序的迭代器
//        E element():获取元素

他的特点:
在这里插入图片描述

实现类ArrayDeque

特点

  1. ArrayDeque是Deque的子实现
  2. 数据结构表现:队列,栈,双端队列
  3. 底层实现: 循环数组要理解一下循环数组的好处。
  4. 存储元素有序
  5. 存储元素可重复
  6. 不可存储null
    用法都是Deque的api。

现在解决栈和队列的问题基本上不会使用Stack而是推荐使用ArrayDeque。
主要原因:
1.性能问题,Stack继承Vector,而Vector是线程安全的,所以有额外的开销。
2.ArrayDeque提供更全面的功能,既能够用来作为栈,又可以作为队列使用
3.Stack现在被认为是过时了,现在一般用Deque来替代Stack。


实战中ArrayDeque怎么用

ArrayDeque 的主要方法

添加元素

addFirst(E e) / offerFirst(E e): 在前端添加元素
addLast(E e) / offerLast(E e): 在后端添加元素
add(E e) / offer(E e): 在后端添加元素(等同于 addLast/offerLast)
push(E e): 在前端添加元素(等同于 addFirst)

移除元素

removeFirst() / pollFirst(): 移除并返回前端元素
removeLast() / pollLast(): 移除并返回后端元素
remove() / poll(): 移除并返回前端元素(等同于 removeFirst/pollFirst)
pop(): 移除并返回前端元素(等同于 removeFirst)

查看元素(不移除):

getFirst() / peekFirst(): 返回前端元素
getLast() / peekLast(): 返回后端元素
peek(): 返回前端元素(等同于 peekFirst)
其他操作:

size(): 返回元素数量
isEmpty(): 检查是否为空
clear(): 清空所有元素
contains(Object o): 检查是否包含特定元素

算法题中的推荐用法:
当用作栈时

push(E e): 压栈
pop(): 出栈
peek(): 查看栈顶元素
isEmpty(): 检查栈是否为空
示例:

Deque<Integer> stack = new ArrayDeque<>();
stack.push(1);
int top = stack.pop();
int peek = stack.peek();

当用作队列时

offer(E e): 入队
poll(): 出队
peek(): 查看队首元素
isEmpty(): 检查队列是否为空
示例:

Deque<Integer> queue = new ArrayDeque<>();
queue.offer(1);
int front = queue.poll();
int peek = queue.peek();

当用作双端队列时
offerFirst(E e) / offerLast(E e): 在前/后端添加元素
pollFirst() / pollLast(): 移除并返回前/后端元素
peekFirst() / peekLast(): 查看前/后端元素
isEmpty(): 检查是否为空
示例:

Deque<Integer> deque = new ArrayDeque<>();
deque.offerFirst(1);
deque.offerLast(2);
int front = deque.pollFirst();
int back = deque.pollLast();

推荐使用这些方法的原因:

它们在元素为 null 或双端队列为空时不会抛出异常,而是返回 null 或 false,这样可以简化错误处理。
这些方法名称清晰地表明了它们的用途和操作的位置(前端或后端)。
它们与 Queue 和 Stack 接口的方法名称保持一致,使代码更易读和理解。

所以说ArrayDeque非常万能,当你在做题的时候如果要用到相关的数据结构,就按上面的流程来走。可以模拟队列,栈,双端队列。

232.用栈实现队列

做题前注意:题目说了每个操作都是合法的,所以不要去做不合法的判断了

假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)。所以不用想这些极端情况。

题的本质:
后进先出实现先进先出
凭我们对栈的理解,显然一个栈是不能完成这个任务的,所以解题思路是用两个栈来完成。

解题思路:
一个栈为入队栈,一个栈为出队栈。
出队的逻辑
当出队栈存在内容时,出队栈的栈顶,即为第一个出队的元素。
如果出队栈内无元素,此时又需要出栈,那么入队栈的所有元素逐个弹出装入出队栈,然后弹出栈顶元素即可。
入队的逻辑:直接装入入队栈。

当两个栈都空了,就表示队空了。
下面是模拟的过程请添加图片描述
来看具体解法

class MyQueue {
	//这是定义接口,然后初始化指定实现类的写法。一般比较推荐这种写法
    Deque<Integer> stOut,stIn;
    
	//指定实现类为ArrayDeque,因为比较万能
	//ArrayDeque可以用来模拟栈,由于需要两个栈,那就开两个ArrayDeque。
    public MyQueue() {
        stIn = new ArrayDeque<>();
        stOut = new ArrayDeque<>();
    }
    
    public void push(int x) {
        //push直接放入进队栈
        stIn.push(x);
    }
    
    public int pop() {
    //出队就从出队栈出,如果出队栈为空,那就要把入队栈中的元素依次弹出然后压入入队栈。自己模拟一下就懂了。
        if(stOut.isEmpty()){
            while(!stIn.isEmpty()){
                stOut.push(stIn.pop());
            }
        }
        return stOut.pop();
        
    }
    //直接用pop方法,接住了再放回去
    public int peek() {
        int res = this.pop();
        stOut.push(res);
        return res;
    }
    //出队栈和入队栈都没有元素,那就是空。
    public boolean empty() {
        return stIn.isEmpty() && stOut.isEmpty();
    }
}


225. 用队列实现栈

题意:用两个队列实现栈即,用两个前进迁出实现后进先出。
思路:
看完这个图就懂了
请添加图片描述
进栈逻辑
就是直接入队1。
出栈逻辑
把队1里面的元素全部倒出来,然后最后一个元素出队。然后倒出来的元素又逐个入队2。之后又把队2全部出队又进队1中。

class MyStack {
    
    Deque<Integer> que1; // 和栈中保持一样元素的队列
    Deque<Integer> que2; // 辅助队列

    public MyStack() {
        que1 = new ArrayDeque<>();
        que2 = new ArrayDeque<>();
    }
    
    
    public void push(int x) {
        que1.offerLast(x);
    }
    
    
    public int pop() {
        int size = que1.size();
        size--;
        
        while (size-- > 0) {
            que2.offerLast(que1.peekFirst());
            que1.pollFirst();
        }

        int res = que1.pollFirst();
        
        que1 = que2;
        
        que2 = new ArrayDeque<>();
        return res;
    }
    
    
    public int top() {
        return que1.peekLast();
    }
    
    
    public boolean empty() {
        return que1.isEmpty();
    }
}

本题总结:这个题不难,对于我来说难的是不知道这么多api用哪个比较好,混用有没有风险。
因此这里做个总结:
队列(Queue)风格操作: 添加:offer(E e) 删除:poll() 查看:peek()

这组方法适合当你想要实现一个标准的队列(先进先出)时使用。它们在操作失败时不会抛出异常,而是返回特殊值。

双端队列(Deque)风格操作: 添加:offerFirst(E e), offerLast(E e) 删除:pollFirst(), pollLast() 查看:peekFirst(), peekLast()

当你需要在队列的两端进行操作时,这组方法很有用。它们也不会在操作失败时抛出异常。

抛出异常的操作: 添加:addFirst(E e), addLast(E e), add(E e) 删除:removeFirst(), removeLast(), remove() 查看:getFirst(), getLast()

这组方法在操作失败时会抛出异常(如 NoSuchElementException)。如果你希望立即捕获和处理异常,可以使用这组方法。

List风格操作: 添加:add(E e), add(int index, E element) 删除:remove(int index), remove(Object o) 查看:get(int index)

虽然 ArrayDeque 不是 List,但这些方法使其在某些情况下可以像 List 一样使用。

栈(Stack)风格操作: 添加:push(E e) (等同于 addFirst(E e)) 删除:pop() (等同于 removeFirst()) 查看:peek() (等同于 peekFirst())

当你使用 ArrayDeque 实现栈时,这组方法最为合适。

推荐的使用方式:

如果你在实现一个标准队列,使用 offer(), poll(), peek()。
如果你需要双端队列功能,使用 offerFirst(), offerLast(), pollFirst(), pollLast(), peekFirst(), peekLast()。
如果你在实现一个栈,使用 push(), pop(), peek()。
如果你希望操作失败时抛出异常,使用 add…, remove…, get… 系列方法。
记住,保持一致性是关键。选择一组方法后,尽量在整个实现中坚持使用这组方法,这样可以使你的代码更加清晰和易于理解。


20. 有效的括号

我的非常直观的写法:

class Solution {
    public boolean isValid(String s) {
        Deque<Character> stack = new ArrayDeque<>();
        
        for (char c : s.toCharArray()) {
            if (c == '(' || c == '[' || c == '{') {
                // 如果是左括号,入栈
                stack.push(c);
            } else {
                // 如果是右括号
                if (stack.isEmpty()) {
                    // 如果栈为空,说明没有匹配的左括号,返回 false
                    return false;
                }
                
                // 检查栈顶元素是否匹配
                char top = stack.pop();
                if (c == ')' && top != '(') return false;
                if (c == ']' && top != '[') return false;
                if (c == '}' && top != '{') return false;
            }
        }
        
        // 最后检查栈是否为空,如果为空说明所有括号都匹配了
        return stack.isEmpty();
    }
}

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

class Solution {
    public String removeDuplicates(String s) {
        char[] str = s.toCharArray();
        Deque<Character> st = new ArrayDeque<>();

        for(int i = 0;i<str.length;i++){
            if(st.isEmpty()){
                st.push(str[i]);
            }else{
                char top = st.peek();
                if(str[i]==top){
                    st.pop();
                }else{
                    st.push(str[i]);
                }
            }
        }
        StringBuilder res = new StringBuilder();
        while(!st.isEmpty()){
            char c = st.pollLast();
            res.append(c);
        }
        return res.toString();

    }
}

今天做题刚总结的,也是我恶心了好久的问题:
ArrayDeque模拟这些结构的时候,光知道api有啥用还不够,方向更是恶心人。

重点

对于 ArrayDeque:双端队列

左边是队首(First)
右边是队尾(Last)

这意味着:

当用作队列时
左边是队首,右边是队尾
从右边(队尾)添加元素:offer(), add(), addLast()
从左边(队首)移除元素:poll(), remove(), removeFirst()

当用作栈时
右边是栈底,左边是栈顶。
从左边(队首)添加和移除元素:push() (等同于 addFirst()), pop() (等同于 removeFirst())
查看栈顶元素:peek() 或 peekFirst()

当做双端队列时:
左边时队首,右边时队尾

左边(队首/First)对应的方法
添加元素:
addFirst(e)
offerFirst(e)
push(e) (当用作栈时)

移除元素:
removeFirst()
pollFirst()
pop() (当用作栈时)

查看元素(不移除):
getFirst()
peekFirst()
peek() (当用作栈或队列时)

右边(队尾/Last)对应的方法
添加元素:
addLast(e)
offerLast(e)
add(e) (当用作队列时)
offer(e) (当用作队列时)

移除元素:
removeLast()
pollLast()

查看元素(不移除):
getLast()
peekLast()

另一组方法:poll和offer
左边(队首/First)对应的方法

添加元素:
offerFirst(e)

移除元素:
pollFirst()

查看元素(不移除):
peekFirst()

右边(队尾/Last)对应的方法

添加元素:
offerLast(e)
offer(e) (当用作队列时,等同于 offerLast(e))

移除元素:
pollLast()

查看元素(不移除):
peekLast()

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

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

相关文章

软考高级里《系统架构设计师》容易考吗?

我还是22年通过的架构考试。系统架构设计师属于软考高级科目&#xff0c;难度比初级和中级都要大&#xff0c;往年的通过率也比较低&#xff0c;一般在10-20%左右。从总体来说&#xff0c;这门科目确实是不好过的&#xff0c;大家如果想要备考系统架构设计师的话&#xff0c;还…

【界面态】霍尔效应表征氮化对SiC/SiO2界面陷阱的影响

引言 引言主要介绍了硅碳化物&#xff08;SiC&#xff09;金属-氧化物-半导体场效应晶体管&#xff08;MOSFETs&#xff09;作为新一代高压、低损耗功率器件的商业化背景。SiC MOSFETs因其优越的电气特性&#xff0c;在高电压和高温应用领域具有巨大的潜力。然而&#xff0c;尽…

Leedcode刷题——7 滑动窗口 双指针

注&#xff1a;以下代码均为c 1. 两数之和2&#xff08;输入有序数组&#xff09; // 法1&#xff1a;暴力 vector<int> twoSum1(vector<int>& numbers, int target) {vector<int> ans(2);int n numbers.size();for(int i 0; i < n-1; i){if(i ! 0…

预算有限?如何挑选经济适用的安全管理系统?

如今&#xff0c;无论是信息安全、生产安全还是人员安全&#xff0c;都直接关系到企业的稳定运营和长远发展。然而&#xff0c;对于许多中小企业而言&#xff0c;高昂的安全管理系统投入往往成为一大难题。那么&#xff0c;在预算有限的情况下&#xff0c;如何挑选一款既经济适…

Camera Raw:常规工具

在 Camera Raw 窗口右下角提供了四个常用的工具&#xff0c;它们分别是&#xff1a;缩放工具、抓手工具、切换取样器叠加以及切换网格叠加工具。 ◆ ◆ ◆ 缩放工具 Zoom Tool 用于放大或缩小预览图像&#xff0c;便于查看和编辑细节。 快捷键&#xff1a;Z 1、双击“缩放工具…

瓦罗兰特游戏帧数低怎么办 瓦罗兰特游戏帧率提不上去怎么解决

瓦罗兰特是一款由拳头游戏&#xff08;Riot Games&#xff09;开发的5v5英雄射击游戏。结合了MOBA元素&#xff0c;每个角色都拥有四个独特的技能&#xff1b;提供了多种游戏模式&#xff0c;如5V5战术射击等&#xff1b;角色和皮肤设计丰富。游戏中&#xff0c;玩家将扮演各具…

uniapp 表格,动态表头表格封装渲染

1.接口表格数据&#xff1a; {"headers": [{"label": "实例名","name": "v1","order": 1,"hide": false,"dateTypeValue": null},{"label": "所属科室","name&quo…

MATLAB数据统计描述和分析

描述性统计就是搜集、整理、加工和分析统计数据&#xff0c; 使之系统化、条理化&#xff0c;以显示出数据资料的趋势、特征和数量关系。它是统计推断的基础&#xff0c;实用性较强&#xff0c;在数学建模的数据描述部分经常使用。 目录 1.频数表和直方图 2 .统计量 3.统计…

Tensorflow之损失函数与交叉熵

损失函数&#xff1a;预测值与已知答案之间的差距 NN优化目标&#xff1a;loss最小{mse&#xff0c; 自定义&#xff0c; ce) 均方误差tensorflow实现&#xff0c;loss_mse tf.reduce_mean(tf.sqrue(y_-y) 预测酸奶日销量&#xff0c;y&#xff0c;x1, x2是影响日销量的因素…

掌握三菱Q系列QD75运动控制模块

跟着资深三菱电气工程师严老师&#xff0c;一起来学习如何使用三菱QD75系列定位模块来完成各种运动控制需求&#xff0c;本课程专门讲解这个三菱QD75定位模块&#xff0c;如果你不知道如何使用QD75模块或者说对QD75模块背后的理论和使用方法不是很熟悉的话&#xff0c;一定要来…

数据高效交互丨DolphinDB Redis 插件使用指南

DolphinDB 是一个高性能的分布式数据库。通过 Redis 插件&#xff0c;DolphinDB 用户可以轻松地与 Redis 数据库进行交互。用户不仅可以从 DolphinDB 向 Redis 发送数据&#xff0c;实现高速的数据写入操作&#xff1b;还可以从 Redis 读取数据&#xff0c;将实时数据流集成到 …

android13 设置左右分屏修改为单屏幕,应用分屏改为单屏

1.前言 android13中,系统设置变成,左边是一级菜单,右侧是二级菜单, 这样跟我们以前android7/8/9的布局是不一样的,我们需要将它修改为一级菜单,点进去才是二级菜单这种。 效果如下 2.系统设置实现分析 它这里使用的是google新出的embedding activity, 相关的知识这里…

【福利】代码公开!咸鱼之王自动答题脚本

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;欢迎[点赞、收藏、关注]哦~ 微信或QQ打开咸鱼之王小程序&#xff0c;进入答题界面&#xff0c;运行main.py。期间不要动鼠标。 可自行更改代码来适配自己的需求~ 可以按照示例图片…

欧拉部署nginx

1.下载nginx 下载地址&#xff1a;https://nginx.org/en/download.html 选择稳定版本 下的镜像文件进行下载 2.解压Nginx包 cd /root/nginx tar -zxvf nginx-1.26.0.tar.gz cd nginx-1.26.03.安装nginx相关依赖 yum -y install gcc zlib zlib-devel pcre-devel openssl o…

数据结构(初阶2.顺序表)

文章目录 一、线性表 二、顺序表 2.1 概念和结构 2.2 分类 2.2.1 静态顺序表 2.2.2 动态顺序表 2.3动态顺序表的实现 1.SeqList.h 2.SeqList.c 打印顺序表 初始化 销毁 增容 尾插 头插 在指定位置之前插入数据 尾删 头删 在指定位置删除数据 3.test.c 一、线性表 线性表&#…

浏览器中js外挂脚本的执行方式

1、开发工具控制台交互执行 网页中按F12打开开发者工具&#xff0c;选择“控制台”&#xff0c;键入js脚本命令回车执行&#xff0c;适用于临时使用脚本逻辑简单的场景&#xff0c;实例如下&#xff1a; // 获取网页元素的文本脚本 var elem document.getElementById("…

开发个人Go-ChatGPT–6 OpenUI

开发个人Go-ChatGPT–6 OpenUI Open-webui Open WebUI 是一种可扩展、功能丰富且用户友好的自托管 WebUI&#xff0c;旨在完全离线运行。它支持各种 LLM 运行器&#xff0c;包括 Ollama 和 OpenAI 兼容的 API。 功能 由于总所周知的原由&#xff0c;OpenAI 的接口需要密钥才…

Zabbix Sia Zabbix 逻辑漏洞(CVE-2022-23134)

前言 CVE-2022-23134是一个中等严重度的漏洞&#xff0c;影响Zabbix Web前端。这个漏洞允许未经身份验证的用户访问setup.php文件的某些步骤&#xff0c;这些步骤通常只对超级管理员开放。利用这个漏洞&#xff0c;攻击者可以通过跳过某些步骤来重新配置Zabbix前端&#xff0c…

Qt 线程同步机制 互斥锁 信号量 条件变量 读写锁

qt线程同步 Qt提供了丰富的线程同步机制来帮助开发者更高效和安全地进行多线程编程。其主要包括: QMutex:为共享数据提供互斥访问能力,避免同时写入导致的数据冲突。利用lock()/unlock()方法实现锁定和解锁。 QReadWriteLock:读写锁,允许多个读线程同时访问,但写操作需要独占…

Java面试八股之MySQL中int(10)和bigint(10)能存储读的数据大小一样吗

MySQL中int(10)和bigint(10)能存储读的数据大小一样吗 在MySQL中&#xff0c;int(10)和bigint(10)的数据存储能力并不相同&#xff0c;尽管括号内的数字&#xff08;如10&#xff09;看起来似乎暗示着某种关联&#xff0c;但实际上这个数字代表的是显示宽度&#xff0c;而不是…