算法队列与栈—Java版

news2024/11/14 17:08:57

队列、双向队列、栈 — ArrayDeque

  • 使用双向队列ArrayDeque可以完成以上三种数据结构。队列的操作包括:入队、出队、返回队首元素、返回队尾元素、删除队首元素、删除队尾元素、判断空、返回队列长度。双向队列包括:首尾入队、首尾出队、返回首尾元素、删除首尾元素、判断空、返回队列长度。栈包括:入栈、出栈、返回栈顶元素、返回栈尾元素、判断空,返回栈长度。

双向队列:

  • addFirst(E e) 在此deque前面插入指定的元素。

  • addLast(E e) 在此deque的末尾插入指定的元素。

  • getFirst() 检索,但不删除,这个deque的第一个元素。 如果此deque为空,则报错。

  • getLast() 检索,但不删除,这个deque的最后一个元素。 如果此deque为空,则报错。

  • removeFirst() 检索并删除此deque的第一个元素。 如果此deque为空,则报错。

  • removeLast() 检索并删除此deque的最后一个元素。 如果此deque为空,则报错。

  • size() 返回此deque中的元素数。

  • contains(Object o) 如果此deque包含指定的元素,则返回 true 。

  • clear() 从这个deque中删除所有的元素。

 @Test
 public void my_queue(){
        ArrayDeque<Integer> arrdeq = new ArrayDeque<>();
        arrdeq.add(3);
        arrdeq.add(9);
        arrdeq.add(0);

        arrdeq.addFirst(1);
        arrdeq.addLast(2);

        boolean con = arrdeq.contains(9);
        Integer peekf = arrdeq.peekFirst(); //返回队头元素,如果此deque为空,则报错。
        Integer peekl = arrdeq.peekLast();//返回队尾元素,如果此deque为空,则报错。

        Integer pf = arrdeq.pollFirst();//队头元素出队并返回,如果此deque为空,则报错。
        Integer pl = arrdeq.pollLast();//队尾元素出队并返回,如果此deque为空,则报错。

        boolean empty = arrdeq.isEmpty();
        arrdeq.clear();
    }
  • Note: 只要掌握了上面的双向队列的操作,那么栈和队列的操作也就会了。注意,最好使用如果队列为空报错的操作而不使用返回null的操作,因为,为空报错对于算法是好的,而返回null有时候很难发现错误!

堆(优先队列)— PriorityQueue

  • add(E e) 将指定的元素插入到此优先级队列中。

  • peek() 检索但不删除此队列的头,如果此队列为空,则返回 null 。

  • poll() 检索并删除此队列的头,如果此队列为空,则返回 null 。

  • remove(Object o) 从该队列中删除指定元素的单个实例(如果存在)。

  • size() 返回此集合中的元素数。

  • toArray() 返回一个包含此队列中所有元素的数组。

  • contains(Object o) 如果此队列包含指定的元素,则返回 true 。

@Test
public void my_priorityQueue(){
        // 默认小根堆,如果要大根堆,只需要乘以-1即可,然后结果再恢复
        PriorityQueue<Integer> pq = new PriorityQueue<Integer>();
        pq.add(9);
        pq.add(1);
        pq.add(4);

        Integer peek = pq.peek();
        Integer poll = pq.poll();
        boolean res = pq.remove(1);
    }

232. 用栈实现队列

  • 此题,使用基本栈实现队列,需要两个栈,一个为输入栈,当输入的时候按顺序入栈即可;另外一个为输出栈,需要把输入栈里的元素全部出栈到输出栈中,即倒置元素到输出栈中,如下图所示(图片来源:代码随想录);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YBlBb1pi-1676785450252)(https://code-thinking.cdn.bcebos.com/gifs/232.%E7%94%A8%E6%A0%88%E5%AE%9E%E7%8E%B0%E9%98%9F%E5%88%97%E7%89%88%E6%9C%AC2.gif)]

import java.util.ArrayDeque;
public class MyQueue {
    ArrayDeque<Integer> stack_in;
    ArrayDeque<Integer> stack_out;
    public MyQueue() {
        stack_in = new ArrayDeque<>();
        stack_out = new ArrayDeque<>();
    }

    public void push(int x) {
        stack_in.addLast(x);
    }
    public int pop() {
        // 如果输出栈还有元素,先用出栈
        if(!stack_out.isEmpty()){
            Integer p = stack_out.removeLast();
            return p;
        }
        //else 否则
        while (!stack_in.isEmpty()){
            Integer last = stack_in.removeLast();
            stack_out.addLast(last);
        }
        Integer p = stack_out.removeLast();
        return p;
    }

    public int peek() {
        // 如果输出栈还有元素,先用出栈
        if(!stack_out.isEmpty()){
            Integer p = stack_out.getLast();
            return p;
        }
        //else 否则
        while (!stack_in.isEmpty()){
            Integer last = stack_in.removeLast();
            stack_out.addLast(last);
        }
        Integer p = stack_out.getLast();
        return p;
    }
    public boolean empty() {
        if(stack_out.isEmpty() && stack_in.isEmpty()){
            return true;
        }
        return false;
    }
}

225. 用队列实现栈

思路,使用两个队列,当入队时,向非空的一个队列中入队,另外一个队列作为辅助队列用于存储挡在前面的元素。两个队列循环作为辅助队列使用,即空的那个即为辅助队列。注明:图片来源代码随想录!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2oSDPuMm-1676785450254)(https://code-thinking.cdn.bcebos.com/gifs/225.%E7%94%A8%E9%98%9F%E5%88%97%E5%AE%9E%E7%8E%B0%E6%A0%88.gif)]

import java.util.ArrayDeque;
public class MyStack {
    ArrayDeque deque1;
    ArrayDeque deque2;
    public MyStack() {
        deque1 = new ArrayDeque<Integer>();
        deque2 = new ArrayDeque<Integer>();
    }

    public void push(int x) {
        if(!deque1.isEmpty()){
            deque1.addLast(x);
        }else if(!deque2.isEmpty()){
            deque2.addLast(x);
        }else {
            deque1.addLast(x);
        }
    }

    public int pop() {
        ArrayDeque<Integer> deque = null;
        ArrayDeque<Integer> helpdeq = null;
        if(!deque1.isEmpty()){
            deque = deque1;
            helpdeq = deque2;
        }
        if(!deque2.isEmpty()){
            deque = deque2;
            helpdeq = deque1;
        }
        while (deque.size()>1){
            Integer value = deque.removeFirst();
            helpdeq.addLast(value);
        }
        // 当deque.size()==1
        Integer p = deque.removeFirst();
        return p;
    }

    public int top() {
        int pop = pop();
        push(pop);
        return pop;
    }

    public boolean empty() {
        if(deque2.isEmpty() && deque1.isEmpty()){
            return true;
        }else {
            return false;
        }
    }
}

LeetCode练习

347. 前 K 个高频元素

思路:先统计,再使用优先队列。

public int[] topKFrequent(int[] nums, int k) {
        TreeMap<Integer, Integer> map = new TreeMap<>();
        PriorityQueue<Map.Entry<Integer, Integer>> pq = new PriorityQueue<>(new Comparator<Map.Entry<Integer, Integer>>() {
            @Override
            public int compare(Map.Entry<Integer, Integer> o1, Map.Entry<Integer, Integer> o2) {
                return o2.getValue()-o1.getValue();
            }
        });
        for(int a: nums){
            //  map.put(num,map.getOrDefault(num,0)+1);
            if(map.containsKey(a)){
                map.replace(a,map.get(a)+1);
            }else {
                map.put(a,1);
            }
        }
        Set<Map.Entry<Integer, Integer>> entries = map.entrySet(); //转为集合
        ArrayList<Map.Entry<Integer, Integer>> arr = new ArrayList<>(entries); //转为数组

        for (int i = 0; i < arr.size(); i++) {
            pq.add(arr.get(i));
        }
//        Collections.sort(arr, new Comparator<Map.Entry<Integer, Integer>>() {
//            @Override
//            public int compare(Map.Entry<Integer, Integer> o1, Map.Entry<Integer, Integer> o2) {
//                return o1.getValue()-o2.getValue();
//            }
//        });
        int[] res = new int[k];
        for (int i = 0; i < k; i++) {
            Map.Entry<Integer, Integer> poll = pq.poll();
            res[i] = poll.getKey();
        }
        return res;
    }

735. 行星碰撞

public int[] asteroidCollision(int[] asteroids) {
        ArrayDeque<Integer> stack = new ArrayDeque<>();
        for(int a : asteroids){
            if(stack.isEmpty() || (stack.getLast()<0 && a>0) || stack.getLast()*a>0){
                // 如果栈为空,或者<-- -->这样的方向,或者同向,直接加进来,因为这些都喷不到
                stack.addLast(a);
            }else {
                while(!stack.isEmpty() && (stack.getLast()>0 && a<0) && Math.abs(stack.getLast())<Math.abs(a)){
                    stack.pollLast();
                }
                //因为空结束,同向结束
                if(stack.isEmpty()||stack.getLast()*a>0){
                    stack.addLast(a);
                }
                //因为质量相等结束,条件要求会碰才能消除
                else if(Math.abs(stack.getLast())==Math.abs(a) && (stack.getLast()>0 && a<0)){
                    stack.pollLast();
                }
            }
        }
        int[] res = new int[stack.size()];
        int i=0;
        while (!stack.isEmpty()){
            res[i] = stack.pollFirst();
            i++;
        }
        return res;
    }

739. 每日温度

public int[] dailyTemperatures(int[] temperatures) {
        // 单调栈,维护一个递减栈
        ArrayDeque<int[]> stack = new ArrayDeque<>();
        int[] res = new int[temperatures.length];
        int[][] temp = new int[temperatures.length][2];
        for (int i = 0; i < temperatures.length; i++) {
            temp[i][0] = i; //第一个记录下标
            temp[i][1] = temperatures[i]; //第二个记录下标对应的温度
        }

        stack.addLast(temp[0]);
        for (int i = 1; i < temp.length; i++) {
            int[] ct = temp[i]; //现在的温度
            while (!stack.isEmpty()){
                if(ct[1]>stack.getLast()[1]){
                    int[] last = stack.pollLast();
                    res[last[0]] = i-last[0];   //出栈:第一个比它大的下标-他自己的下标 就是第几天温度比他高
                }else {
                    stack.addLast(ct);
                    break;
                }
            }
            // 否则栈空就进栈
            stack.addLast(ct);
        }
        return res;
    }

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

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

相关文章

【挣值分析】

名称解释 拼写解释PV计划费用&#xff0c;预估预算EV挣值&#xff0c;实际预估预算AC实际费用&#xff0c;实际花费CV成本偏差 &#xff08;EV - AC&#xff09;SV进度偏差&#xff08;EV - PV&#xff09;CPI成本绩效指数 &#xff08;EV / AC&#xff09;SPI进度绩效指数 &a…

【Kubernetes】【十】Pod详解 Pod介绍与配置

第五章 Pod详解 本章节将详细介绍Pod资源的各种配置&#xff08;yaml&#xff09;和原理。 Pod介绍 Pod结构 每个Pod中都可以包含一个或者多个容器&#xff0c;这些容器可以分为两类&#xff1a; 用户程序所在的容器&#xff0c;数量可多可少 Pause容器&#xff0c;这是每个…

Mybatis(4)之跟着老杜做一个简单的银行转账会话

这是个MVC项目&#xff0c;我不一定可以完整的实现这个项目&#xff0c;但力求把这个复现出来&#xff0c;尽量的复现细节。 第一步&#xff1a;创建数据库 表 创建表如下&#xff1a; 我们使用 int 是为了方便 然后采用 demcial&#xff0c;精确度较高 添加两个用户 然后…

JVM学习笔记二:运行时数据区概述及JVM线程

目录 概述 JVM各区域划分 JVM线程 线程的内存空间 JVM系统线程 概述 运行时数据区是JVM非常重要的组成部分&#xff0c;这一篇主要介绍运行时数据区各个区域的划分&#xff0c;以及JVM中的线程。 JVM各区域划分 学习JVM&#xff0c;必须牢记下图各个区域的分类&#xff…

【5G RRC】5G系统消息SIB2介绍

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G算力网络技术标准研究。 博客…

九龙证券|动力锂离子电池的能量密度可达多少?

现在&#xff0c;我国车用动力锂电池技能道路挑选的是与美国相同的磷酸铁锂道路。毫无疑问&#xff0c;磷酸铁锂离子电池有着许多优势&#xff1a;稳定性高、价格相对便宜&#xff0c;然而其能量密度&#xff08;能量密度更大&#xff0c;才能更好地解决路程问题&#xff09;提…

RabbitMQ 入门到应用 ( 五 ) 基本应用

6.更多应用 6.1.AmqpAdmin 工具类 可以通过Spring的Autowired 注入 AmqpAdmin 工具类 , 通过这个工具类创建 队列, 交换机及绑定 import org.springframework.amqp.core.AmqpAdmin; import org.springframework.amqp.core.Binding; import org.springframework.amqp.core.Di…

linux xargs 删除名字中包含某字符串的文件

xargs的作用 格式化输出 可以把多行文本变成一行&#xff0c;或者指定行数和列数。每一列用空格作分隔符号。 test.txt中的内容 例子1&#xff1a; 用xargs格式化输出后,多行变成了一行&#xff0c;而且多个空格变成了一个空格。 cat test|xargs例子2&#xff1a; 当然也可…

go size class 内存块思考

浏览到的一篇文章&#xff0c;让我也有机会反思一下 go 内存管理。网络上&#xff0c;go 内存管理方面的介绍挺多的&#xff0c;面试的时候&#xff0c;偶尔也会被问到内存管理。 而且&#xff0c;从 go1.15 到 go1.16 在 size class 上引入了新的内存块&#xff0c;能直观的看…

信奥一本通1365

1365&#xff1a;FBI树(fbi) 时间限制: 1000 ms 内存限制: 65536 KB 提交数: 6443 通过数: 4366 【题目描述】 我们可以把由“0”和“1”组成的字符串分为三类&#xff1a;全“0”串称为B串&#xff0c;全“1”串称为I串&#xff0c;既含“0”又含“1”的串则称为…

C语言——动态内存管理(详解)

1.动态内存管理存在的意义 在前面的C语言的学习中&#xff0c;我们已经掌握的空间开辟的方式有如下两种 int i 0; //开辟了4字节大小的空间存放i int arr[5] {0}; //开辟了20字节的空间存放数组arr这样开辟空间有两个显著的特点&#xff1a; 1、每次开辟空间的大小都是固定…

K8S集群将Docker切换到Containerd

文章目录1. 开启节点维护1.1 将节点设置成不可调度1.2 驱逐节点上的 Pod1.3 停止相关服务2. 升级到 containerd2.1 安装 containerd2.2 调整 containerd 配置2.3 修改 kubelet 启动配置参数3. 重启节点服务4. 验证升级后的节点5. 容器管理工具5.1 容器管理命令行工具对比5.2 cr…

【JavaScript】ES6模块化与异步编程高级用法

一、ES6模块化 1、回顾&#xff1a;node.js遵循了ComminJS的模块化规范。 其中&#xff1a; 导入其他模块使用require()方法模块对外共享成员使用module.exports对象 模块化的好处&#xff1a; 遵守同样的模块化规范写代码&#xff0c;降低了沟通成本&#xff0c;极大方便了…

使用 ApiPost进行WebService 调试,就是这样简单

文章目录5.1 新建一个 HTTP 接口5.2 添加请求Body5.3 设置请求Header5.4 发送请求Apipost 可以用于调试 WebService 请求。具体步骤如下&#xff1a;5.1 新建一个 HTTP 接口 新建一个 HTTP接口&#xff0c;URL 部分填写 endpoint&#xff0c;请求方式选择 POST。以下 URL 为示…

SpringBoot自动装配的原理

前言 在开发SpringBoot项目时&#xff0c;当我们引入spring-boot-starter-xxx依赖后&#xff0c;想要使用依赖中的bean&#xff0c;直接就用Autowired拿来用了&#xff0c;不需要用xml或者注解的方式把它先注入到Spring容器中。这就是自动装配的特性&#xff0c;本文来讲述Spri…

Spring Bean循环依赖

解决SpringBean循环依赖为什么需要3级缓存&#xff1f;回答&#xff1a;1级Map保存单例bean。2级Map 为了保证产生循环引用问题时&#xff0c;每次查询早期引用对象&#xff0c;都拿到同一个对象。3级Map保存ObjectFactory对象。数据结构1级Map singletonObjects2级Map earlySi…

CMake option选项使用方式及注意事项

CMAKE官网 &#x1f358; 在复习 CMake 的时候&#xff0c;使用了 option 功能&#xff0c;发现修改了参数的值之后&#xff0c;和未修改的效果一样&#xff0c;然后不断的查找 option 的使用方法&#xff0c;最后发现并非 option 使用方式而错误&#xff0c;而是 option 第一…

SpringCloudAlibaba-分布式事务Seata

一、介绍官网&#xff1a;http://seata.io/zh-cn/index.html TC (Transaction Coordinator) - 事务协调者维护全局和分支事务的状态&#xff0c;驱动全局事务提交或回滚。TM (Transaction Manager) - 事务管理器定义全局事务的范围&#xff1a;开始全局事务、提交或回滚全局事务…

Mac Appium iOS自动化测试环境搭建教程

目录Appium环境搭建Mac iOS环境搭建Appium基础Appium进阶环境搭建安装brewCopyruby -e "$(curl -fsSL https://raw.github.com/mxcl/homebrew/go)"安装javaCopybrew install java安装python3 及相关包Copybrew install python3 pip install selenium pip install app…

实现8086虚拟机(四)——mov 和 jmp 指令解码

文章目录mov 指令解码jmp 指令解码这篇文章举例来讲讲 mov 指令和 jmp 指令解码函数的实现&#xff0c;其他的指令解码函数都与这些类似。mov 指令解码 以 mov 指令中的一类&#xff1a;寄存器/内存 到/从 寄存器&#xff0c;来详细说明解码函数的实现。 机器指令格式如下&am…