java算法day9

news2024/10/3 4:41:12
  • 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()

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

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

相关文章

开源数据 | 语音对话大模型高品质数据集——MagicHub多方言语音数据集推荐

近日&#xff0c;法国知名开源AI研究实验室Kyutai推出了一款具备看、听、说多模态大模型——Moshi。Moshi功能与GPT-4o相似&#xff0c;可以听取人的语音提问后进行实时推理回答内容。然而&#xff0c;Moshi最吸引人的是全面开源&#xff0c;并可以支持在端侧运行。这将大大提振…

ARM裸机:一步步点亮LED(汇编)

硬件工作原理及原理图查阅 LED物理特性介绍 LED本身有2个接线点&#xff0c;一个是LED的正极&#xff0c;一个是LED的负极。LED这个硬件的功能就是点亮或者不亮&#xff0c;物理上想要点亮一颗LED只需要给他的正负极上加正电压即可&#xff0c;要熄灭一颗LED只需要去掉电压即可…

Dynamics365 UCI下的高级查找(不要留恋Classic了)

UCI界面已经用了多年了&#xff0c;在Classic下的的高级查找按钮(漏斗icon)已不见踪影 但因为使用习惯问题&#xff0c;还是有人会通过右上角高级设置&#xff0c;进入Classic界面找到漏斗Icon来使用高级查找 但新的UCI风格下已经没了高级查找的概念&#xff0c;取而代之的是基…

ComfyUI入门教程

本文主要介绍了通过源码运行comfyui&#xff0c;默认例子介绍&#xff0c;节点管理器的使用&#xff0c;以及界面汉化。可多参考开源工作流&#xff0c;多加实践&#xff0c;从而掌握comfyui操作。 1.源码运行comfyui 执行命令python main.py如下&#xff1a; 安装numpy 1.x最…

JavaScript中的LHS和RHS

LHS和RHS之前我们先来回忆一下最简单的赋值操作! var test100; console.log(test); 以上代码的意思简单我们理解为把右边的值赋值给左边的test变量,然后输出打印结果。 可是我们要是深入理解你就会发现在这个过程当中&#xff0c;还发生了一些其他的事情 而这些事情就是今天…

C++入门基础(1)

因为6月中旬学校事情多&#xff0c;许久未更新&#xff0c;让我们继续学习吧&#xff01; 目录 前言&#xff1a; 一、命名空间&#xff1a; 1、定义&#xff1a; 2、使用&#xff1a; 3、访问命名空间域: 二、C输入、输出函数&#xff1a; 1、输入函数&#xff1a; 2、输出…

vue3源码(六)渲染原理-runtime-core

1.依赖关系 runtime-dom 依赖于runtime-core,runtime-core 依赖于reactivity和sharedruntime-core提供跨平台的渲染方法createRenderer&#xff0c;用户可以自己传递节点渲染的渲染方法renderOptions&#xff0c;本身不关心用户使用什么APIruntime-dom提供了为浏览器而生的渲染…

关闭这八个电脑设置,保护个人隐私

你知道吗&#xff1f;电脑可能一直在偷窥你的小秘密。朋友们&#xff0c;一定要记得关闭这8个电脑设置哦&#xff0c;这样可以有效地保护我们的个人隐私。 按住键盘Windows键加i键&#xff0c;快速打开Windows设置。然后点击隐私选项。 我们来看基本的常规设置。里面有四个设置…

关于put提交不了参数的解决办法

html中form表单只支持GET与POST请求&#xff0c;而DELETE、PUT等method并不支持&#xff0c; 如图所示 参数请求改成RequestBody&#xff0c;用json格式传参即可解决问题

资料分析笔记整理

提升技巧多做题、少动笔、多分析 资料分析认识 国考一般20题(24~28分钟) 统计材料的类型包括单纯的文字、表格、图形以及由这些元素组成的复合类型材料 文字性材料:(30~60秒) 多段落型文字材料(时间、关键词、结构) 孤立段落文字材料(时间、关键词、标点[。;]) 表…

数据挖掘——matplotlib

matplotlib概述 Mat指的是Matlab&#xff0c;plot指的是画图&#xff0c;lib即library&#xff0c;顾名思义&#xff0c;matplotlib是python专门用于开发2D图表的第三方库&#xff0c;使用之前需要下载该库&#xff0c;使用pip命令即可下载。 pip install matplotlib1、matpl…

Idea使用EasyApi插件自动生成接口文档到Yapi

1.安装EasyApi插件 2.配置Yapi 设置-》EasyApi Yapi的Server 配置为Yari项目的地址 tokens&#xff1a;项目名Yapi项目里面的token&#xff1a;例如&#xff1a;test-project0e6cfb3c22c884a0fce108fffe554a20ca12341e421d7201233143ee440af36b mytest-portal0e6cfb3c22c884a…

关于Qt模型插入最后一行数据中存在未填满的项,点击导致崩溃的解决办法

在使用Qt模型视图框架的时候&#xff0c;你可能会遇见这种情况&#xff1a;给QTableView设置设置模型的时候&#xff0c;网模型里面插入数据&#xff0c;因为数据是一行一行插入的&#xff0c;即要使用model的appandRow函数&#xff0c;但有时候最后一行数据没有填满一行&#…

Temu是什么?Temu自养号测评有什么优势?

一、 Temu是什么&#xff1f;Temu是拼多多于海外线的跨境电商平台&#xff0c;“Temu”这个名字的含义也和拼多多的意思相近。Temu跨境电商自上线以来&#xff0c;下载量不断攀升&#xff0c;发展势头一片大好&#xff0c;击穿地板价的商品在欧美市场掀起了一阵狂潮&#xff0c…

html H5 dialog弹窗学习,实现弹窗显示内容 替代confirm、alert

html H5 dialog弹窗学习,实现弹窗内容 替代confirm 框架使用的mui,使用mui.confirm() 弹窗内容过多时,弹窗被撑的到屏幕外去了,使用H5 dialog 标签自定义一个固定大小的弹窗,内容过多时可下拉显示 效果展示 隐私政策内容很多,可以下拉显示 代码 myDialog.css dialog{p…

Java虚拟机面试题汇总

目录 1. JVM的主要组成部分及其作用&#xff1f; 1.1 运行时数据区划分&#xff1f; 1.2 哪些区域可能会发生OOM&#xff1f; 1.3 堆和栈的区别&#xff1f; 1.4 内存模型中的happen-before是什么&#xff1f; 2. HotSpot虚拟机对象创建流程&#xff1f; 2.1 类加载过程…

Xilinx zc706 USB电路解析

作者 QQ群&#xff1a;852283276 微信&#xff1a;arm80x86 微信公众号&#xff1a;青儿创客基地 B站&#xff1a;主页 https://space.bilibili.com/208826118 参考 USB OTG检测原理 USB3320 USB_ID为低电平时候&#xff0c;为host模式&#xff0c;USB_ID为悬空&#xff08;高…

如何快速实现一个无缝轮播效果

&#x1f9d1;‍&#x1f4bb; 写在开头 点赞 收藏 学会&#x1f923;&#x1f923;&#x1f923; 需求简介 轮播图是我们前端开发中的一个常见需求&#xff0c;在项目开发中&#xff0c;我们可以使用element、ant等UI库实现。某些场景&#xff0c;为了一个简单的功能安装一…

数据结构作业/2024/7/9

2>实现双向循环链表的创建、判空、尾插、遍历、尾删、销毁 fun.c #include "head.h" //1.双向循环链表的创建 doubleloop_ptr create_list() …

面经-计算机网络-数据结构-堆

1.什么是堆 堆是一种满足以下条件的树&#xff1a; 堆中的每一个节点值都大于等于&#xff08;或小于等于&#xff09;子树中所有节点的值。或者说&#xff0c;任意一个节点的值都大于等于&#xff08;或小于等于&#xff09;所有子节点的值。 2.堆的用途 当我们只关心所有数…