【华为OD题库-038】支持优先级的对列-java

题目

实现一个支持优先级的队列,高优先级先出队列,同优先级时先进先出。
如果两个输入数据和优先级都相同,则后一个数据不入队列被丢弃。
队列存储的数据内容是一个 整数。
输入描述
一组待存入队列的数据(包含内容和优先级)。
输出描述
队列的数据内容(优先级信息输出时不再体现)。
补充说明
不用考虑数据不合法的情况,测试数据不超过100个。
示例1
输入:
(10,1),(20,1).(30,2).(40,3)
输出:
40,30,10,20
说明:
输入样例中,向队列写入了4个数据,每个数据由数据内容和优先级组成。输入和输出内容都不含空格。数据40的优先级最高,所以最先输出,其次是30;10和20优先级相同,所以按输入顺序输出
示例2
输入:
(10,1),(10,1).(30,2).(40,3)
输出:
40,30,10
说明:
输入样例中,向队列写入了4个数据,每个数据由数据内容和优先级组成输入和输出内容都不含空格。
数据40的优先级最高,所以最先输出,其次是30;两个10和10构成重复数据,被丢弃一个。

思路

基础的数据结构题,大概三个思路:

  1. 直接放入list,转对象排序,可以实现要求
  2. 使用内置的PriorityQueue对象实现
  3. 自定义数据结构实现

猜测考察点在第三点,不然前两个虽然能达到目的,但是没有意义

排序实现

分析题目,排序规则为:

  1. 优先级高的先出,
  2. 同优先级时位置靠前的先出;
  3. 数据和优先级均相同的去重

基于以上分析,可以采用以下步骤实现:

  1. 新建一个data对象,含有priority,val,idx三个属性,idx代表出现位置
  2. 把输入转为data对象放入list中
  3. 先去重(利用HashSet),根据priority,val判重,重写equals方法
  4. 自定义排序规则,priority降序,idx升序排列。Data实现Comparable接口,重写compareTo方法

PriorityQueue实现

还是一样,新建Data对象,重写equals(去重用)和compareTo(排序用)方法
把输入转为Data对象后,直接加入PriorityQueue中
重复对象都加入到了PriorityQueue,在输出时,因为结果已经按照自定义排序规则写好了,所以去重逻辑就是当前项等于上一项时,代表重复,此时不输出对应结果即可

自定义数据结构实现

可以用两个栈实现优先级队列
stackA:优先级高的在栈顶,存放较小优先级
stackB:优先级低的在栈顶,存放较大优先级,也就是说在stackB中的优先级始终比stackA的优先级大,比如某个状态如下:
在这里插入图片描述
最后再输出结果时,只需要把stackB依次出栈再入stackA栈,再输出stackA的栈顶元素即可得到:6,5,4,3,2,1。即按优先级降序排列。
具体存放数据逻辑如下,以20 10 30 40 50为例:

  1. 存入20,首先判断它是较大优先级还是较小优先级?我们可以和stackB的栈顶元素比较(当然和stackA的栈顶元素比较也可以)。如果cur<stackB.peek()。说明是一个比stackB最低优先级还要小的元素,所以它是一个较小优先级,应该存入stackA中。此处stackB为空,没有栈顶元素,我们也先出入stackA中,由于stackA没有数据,直接存入,如下:
    在这里插入图片描述

  2. 存入10,stackB为空,所以还是存入stackA中,但是此时stackA有数据,由于定义的stackA要将较大优先级放入栈顶,即当前元素如果比stackA的栈顶元素还要小(cur<stackA.peek())时,应该把大于当前优先级的数据转入stackB
    在这里插入图片描述

  3. 存入30,大于stackB的栈顶元素,此时应该存入stackB,同样的逻辑,这里stackB是将优先级小的放入栈顶,所以cur>stackB.peek()时,应该把小于当前优先级的数据转入stackA
    在这里插入图片描述

  4. 存入40,大于stackB栈顶元素,存入stackB,将stackB小于当前优先级的元素放入stackA中
    在这里插入图片描述

  5. 存入50,大于stackB栈顶元素,存入stackB,将stackB小于当前优先级的元素放入stackA中
    在这里插入图片描述

  6. 最后输出结果,需要将stackB中的全部数据转入stackA,再依次从stackA栈顶取数据得到:50 40 30 20 10

上面的过程没有考虑优先级相同和去重时的处理逻辑,现在分析如下:

  1. 优先级相同,比如在上面的数据中再加入一个30,30小于stackB的栈顶元素,所以应该放入stackA中,将stackA大于30的元素全部弹出来:
    在这里插入图片描述
    关键在于等于30是否弹出?如果弹出,那么我们将第二个30加入到了stackA的栈顶,第一个30弹入了stackB的栈顶,最后输出结果时,一定是先输出的第一个30。符合题意,否则的话,会先输出第二个30。所以在stackA入栈时,判断条件是:cur<=stackA.peek()
    假设最后加入的不是30而是50,此时弹出到stackA时,不应该取等,即cur>stackB.peek(),即只弹出比stackB栈顶元素还大的值
    在这里插入图片描述
    如上,因为栈顶和50相等,不弹出stackA,直接加入,最后的结果一定是第一个50先输出来。

  2. 去重,根据第一点,优先级相同时的处理逻辑可以发现,当优先级相同时,始终会把之前的数据放入到stackB中去,所以我们再向stackA或者stackB加入数据时,只要判断其不等于stackB的栈顶元素即可(相等判断逻辑为优先级和值同时相同,重写equals方法实现)

题解

三种方法都定义了实体Data:

class Data implements Comparable<Data> {
    private int priority;
    private int val;
    private int idx;

    public Data(int priority, int val, int idx) {
        this.priority = priority;
        this.val = val;
        this.idx = idx;
    }

    public int getIdx() {
        return idx;
    }

    public void setIdx(int idx) {
        this.idx = idx;
    }

    public int getPriority() {
        return priority;
    }

    public void setPriority(int priority) {
        this.priority = priority;
    }

    public int getVal() {
        return val;
    }

    public void setVal(int val) {
        this.val = val;
    }

    public Data(int priority, int val) {
        this.priority = priority;
        this.val = val;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Data data = (Data) o;
        return priority == data.priority &&
                val == data.val;
    }

    @Override
    public int hashCode() {
        return Objects.hash(priority, val);
    }

    @Override
    public int compareTo(Data o) {
        if (this.priority != o.priority) return o.priority - this.priority;
        return this.idx - o.idx;
    }
}

排序实现

package hwod;

import java.util.*;
import java.util.stream.Collectors;

public class MyPriorityQueue {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String inputs = sc.nextLine();
        System.out.println(myPriorityQueue(inputs));
    }

    /**
     * 直接排序输出
     *
     * @param str
     * @return
     */
    private static String myPriorityQueue(String str) {
        //将输入解析为自定义对象Data
        Set<Data> set = new HashSet<>();
        String[] arrs = str.substring(1, str.length() - 1).split("\\),\\(");
        for (int i = 0; i < arrs.length; i++) {
            String[] cur = arrs[i].split(",");
            set.add(new Data(Integer.parseInt(cur[1]), Integer.parseInt(cur[0]), i));
        }
        List<Data> list = set.stream().sorted().collect(Collectors.toList());
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < list.size(); i++) {
            if (i != 0) sb.append(",");
            sb.append(list.get(i).getVal());
        }
        return sb.toString();
    }
}

PriorityQueue实现

package hwod;

import java.util.*;
import java.util.stream.Collectors;

public class MyPriorityQueue {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String inputs = sc.nextLine();
        System.out.println(myPriorityQueue(inputs));
    }
    /**
     * 使用java自带的优先级队列
     *
     * @param str
     * @return
     */
    private static String myPriorityQueue(String str) {
        //将输入解析为自定义对象Data
        String[] arrs = str.substring(1, str.length() - 1).split("\\),\\(");
        PriorityQueue<Data> queue = new PriorityQueue<>();
        for (int i = 0; i < arrs.length; i++) {
            String[] cur = arrs[i].split(",");
            Data data = new Data(Integer.parseInt(cur[1]), Integer.parseInt(cur[0]),i);
            queue.add(data);
        }
        StringBuilder sb = new StringBuilder();
        Data lst = null;
        int size = queue.size();
        while (!queue.isEmpty()) {
            Data data = queue.poll();
            if (!data.equals(lst)) {
                lst = data;
                if (size != queue.size()+1) sb.append(",");
                sb.append(data.getVal());
            }
        }
        return sb.toString();
    }
}

自定义数据结构实现

package hwod;

import java.util.*;
import java.util.stream.Collectors;

public class MyPriorityQueue {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String inputs = sc.nextLine();
        System.out.println(myPriorityQueue(inputs));
    }
    /**
     * 用两个栈实现优先级对列
     *
     * @param str
     * @return
     */

    private static String myPriorityQueue2(String str) {
        //将输入解析为自定义对象Data
        String[] arrs = str.substring(1, str.length() - 1).split("\\),\\(");
        Myqueue queue = new Myqueue();
        for (int i = 0; i < arrs.length; i++) {
            String[] cur = arrs[i].split(",");
            Data data = new Data(Integer.parseInt(cur[1]), Integer.parseInt(cur[0]));
            queue.add(data);
        }
        StringBuilder sb = new StringBuilder();
        int size = queue.getSize();
        while (!queue.isEmpty()) {
            if (queue.getSize() != size) sb.append(",");
            sb.append(queue.remove().getVal());
        }
        return sb.toString();
    }
}
class Myqueue {
    private LinkedList<Data> stackA = new LinkedList<>();//存小数,大堆顶
    private LinkedList<Data> stackB = new LinkedList<>(); //存大数,小堆顶

    public void add(Data data) {

        if (stackB.isEmpty() || data.getPriority() <= stackB.peekLast().getPriority()) {
            //比stackB栈顶元素还小,说明是一个较低优先级,应该存在stackA中
            //和stackB栈顶元素相等,说明有两个优先级相等的data,比如(30,1),(10,1),题目要求按照输入顺序输出,那么可以等价于后出现的优先级相对更低
            // 即此处的优先级等于和小于等价
            while (!stackA.isEmpty() && data.getPriority() <= stackA.peekLast().getPriority()) {
                stackB.addLast(stackA.removeLast());
            }
            //优先级相等时,始终会把之前的数据放入stackB中去
            if (!stackB.isEmpty() && stackB.peekLast().equals(data)) return;
            stackA.addLast(data);
        } else {
            while (!stackB.isEmpty() && data.getPriority() > stackB.peekLast().getPriority()) {
                stackA.addLast(stackB.removeLast());
            }
            if (!stackB.isEmpty() && stackB.peekLast().equals(data)) return;
            stackB.addLast(data);
        }

    }

    public Data remove() {
        while (!stackB.isEmpty()) {
            stackA.addLast(stackB.removeLast());
        }
        return stackA.removeLast();

    }
    public int getSize() {
        return stackA.size() + stackB.size();
    }
    public boolean isEmpty() {
        return getSize() == 0;
    }
}

推荐

如果你对本系列的其他题目感兴趣,可以参考华为OD机试真题及题解(JAVA),查看当前专栏更新的所有题目。

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

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

相关文章

ubuntu 使用webrtc_ros 编译linux webrtc库

ubuntu 使用webrtc_ros 编译linux webrtc库 webrtc_ros 使用WebRTC流式传输ROS图像主题 该节点提供了一个WebRTC对等方&#xff0c;可以将其配置为流ROS图像主题并接收发布到ROS图像主题的流。 该节点托管一个提供简单测试页面的Web服务器&#xff0c;并提供可用于创建和配置W…

基于springboot实现学生成绩管理系统项目【项目源码+论文说明】

基于springboot实现学生成绩管理系统演示 摘要 随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应运而生&am…

【从浅识到熟知Linux】基本指令之基本权限

&#x1f388;归属专栏&#xff1a;从浅学到熟知Linux &#x1f697;个人主页&#xff1a;Jammingpro &#x1f41f;每日一句&#xff1a;用博客整理整理之前学过的知识&#xff0c;是个不错的选择。 文章前言&#xff1a;本文介绍Linux中的基本权限及相关指令用法并给出示例和…

互联网+智慧工地系统源码

智慧工地以施工现场风险预知和联动预控为目标&#xff0c;将智能AI、传感技术、人像识别、监控、虚拟现实、物联网、5G、大数据、互联网等新一代科技信息技术植入到建筑、机械、人员穿戴设施、场地进出关口等各类设备中&#xff0c;实现工程管理与工程施工现场的整合&#xff0…

快速压缩:迅速减小PDF文件大小的步骤与技巧

虽然png图片格式是一种无损压缩格式&#xff0c;但是png图片的内存大小也是比较大的&#xff0c;而且兼容性上也没有jpg图片好&#xff0c;许多平台推荐的也都是jpg格式&#xff0c;所以当我们需要把png转jpg格式的时候&#xff0c;就需要用到图片格式转换器&#xff0c;今天推…

JAVA创建线程方式有几种

方式1&#xff1a;继承Thread类 步骤&#xff1a; 创建一个继承于Thread类的子类重写Thread的run()方法创建当前Thread子类的对象通过实例对象调用start()方法&#xff0c;启动线程----》JAVA虚拟机会调用run()方法 实现&#xff1a; public class TestMyThread {public sta…

怎样禁止邮件发送涉密信息

数字化时代&#xff0c;电子邮件已成为人们生活和工作中不可或缺的通讯工具。然而&#xff0c;随着互联网的普及&#xff0c;涉密信息的泄露风险也随之增加。为了保护敏感数据&#xff0c;禁止邮件发送涉密信息显得尤为重要。以下是一些建议&#xff0c;帮助你实现这一目标。 1…

buuctf web [极客大挑战 2019]PHP

提示有备份,dirsearch扫描网站备份 GitHub - maurosoria/dirsearch: Web path scanner下载.zip格式文件 解压到python目录下 在上图位置cmd打开窗口 输入python setup.py install安装dirseach 安装好后输入命令使用dirseach python dirseach.py -u http://44296191-973d-448…

在CentOS 7.9上搭建高性能的FastDFS+Nginx文件服务器集群并实现外部远程访问

文章目录 引言第一部分&#xff1a;FastDFS介绍与安装1.1 FastDFS简介1.2 FastDFS安装1.2.1 安装Tracker Server1.2.2 安装Storage Server 1.3 FastDFS配置1.3.1 配置Tracker Server1.3.2 配置Storage Server1.3.3 启动FastDFS服务 第二部分&#xff1a;Nginx配置2.1 Nginx安装…

【深度学习】因果推断与机器学习的高级实践 | 数学建模

文章目录 因果推断因果推断的前世今生&#xff08;1&#xff09;潜在结果框架&#xff08;Potential Outcome Framework&#xff09;&#xff08;2&#xff09;结构因果模型&#xff08;Structual Causal Model&#xff0c;SCM&#xff09; 身处人工智能爆发式增长时代的机器学…

uniapp实现多时间段设置

功能说明&#xff1a; 1 点击新增时间&#xff0c;出现一个默认时间段模板&#xff0c;不能提交 2 点击“新增时间文本”&#xff0c;弹出弹窗&#xff0c;选择时间&#xff0c;不允许开始时间和结束时间同时为00:00&#xff0c; <view class"item_cont"> …

python排序算法_归并排序

什么是归并排序&#xff1a; 归并排序是一种基于分治法的排序算法。它的基本思想是将待排序的序列分成若干个子序列&#xff0c;分别进行排序&#xff0c;然后再将已排序的子序列合并成一个有序的序列。 基本思想&#xff1a; 归并排序是用分治思想&#xff0c;分治模式在每一…

ubuntu22.04 安装 jupyterlab

JupyterLab Install JupyterLab with pip: pip install jupyterlabNote: If you install JupyterLab with conda or mamba, we recommend using the conda-forge channel. Once installed, launch JupyterLab with: jupyter lab

基于人工兔算法优化概率神经网络PNN的分类预测 - 附代码

基于人工兔算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于人工兔算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于人工兔优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神经网络…

CDN的认识与绕过

CDN的认识与绕过 什么是CDN CDN的全称是Content Delivery Network&#xff0c;即内容分发网络。它依靠部署在各地的边缘服务器&#xff0c;通过中心平台的负载均衡、内容分发、调度等功能模块&#xff0c;使用户就近获取所需内容&#xff0c;降低网络拥塞&#xff0c;提高用户…

万字解析设计模式之策略模式、命令模式

一、策略模式 1.1概述 先看下面的图片&#xff0c;我们去旅游选择出行模式有很多种&#xff0c;可以骑自行车、可以坐汽车、可以坐火车、可以坐飞机。 策略模式&#xff08;Strategy Pattern&#xff09;是一个行为型设计模式&#xff0c;它定义了一组算法家族&#xff0c;分…

今年的校招薪资真的让人咋舌!

秋招接近尾声&#xff0c;各大公司基本也陆续开奖了。这里整理了部分公司的薪资情况&#xff0c;数据来源于 OfferShow 和牛客网。 ps&#xff1a;爆料薪资的几乎都是 211 和 985 的&#xff0c;并不是刻意只选取学校好的。另外&#xff0c;无法保证数据的严格准确性。 淘天 …

【实战】K8S Helm部署Redis Cluster Redisinsight

文章目录 前言部署Redis Cluster安装Redis Insight写在最后 前言 在Web服务的开发过程中&#xff0c;Redis一直以来都有着举足轻重的作用。基本上所有的后端服务都会用这个中间件实现具体的业务场景&#xff0c;比如常作为系统缓存、分布式锁&#xff0c;也可以实现排名、定位…

向量机SVM原理理解和实战

目录 概念场景导入 点到超平面的距离公式 最大间隔的优化模型 硬间隔、软间隔和非线性 SVM 用 SVM 如何解决多分类问题 1. 一对多法 2. 一对一法 SVM主要原理和特点 原理 优点 缺点 支持向量机模型分类 SVM实战如何进行乳腺癌检测 数据集 字段含义 代码实现 参…

apple macbook M系列芯片安装 openJDK17

文章目录 1. 查找openjdk版本2. 安装openjdk3. 多jdk之间的切换 在这里我们使用 brew 命令查找并安装。 1. 查找openjdk版本 执行&#xff1a;brew search openjdk&#xff0c;注意&#xff1a;执行命令后&#xff0c;如果得到的结果中没有红框内容&#xff0c;则需要更新一下…