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

news2024/11/17 11:21:48

题目

实现一个支持优先级的队列,高优先级先出队列,同优先级时先进先出。
如果两个输入数据和优先级都相同,则后一个数据不入队列被丢弃。
队列存储的数据内容是一个 整数。
输入描述
一组待存入队列的数据(包含内容和优先级)。
输出描述
队列的数据内容(优先级信息输出时不再体现)。
补充说明
不用考虑数据不合法的情况,测试数据不超过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),查看当前专栏更新的所有题目。

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

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

相关文章

人脑工作机制 基本工作原理 神经元 神经网络 学习和记忆 和身体的互动 模仿游戏

人脑的工作机制非常复杂&#xff0c;涉及多个层面的结构和功能。以下是一些关键点&#xff0c;用以概述人脑的基本工作原理&#xff1a; 基本单位 - 神经元&#xff1a; 人脑包含大约860亿个神经元。神经元是脑的基本工作和信号处理单位&#xff0c;通过树突接收信号&#xff0…

记一次简单的PHP反序列化字符串溢出

今天朋友给的一道题&#xff0c;让我看看&#xff0c;来源不知&#xff0c;随手记一下 <?php // where is flag error_reporting(0); class NFCTF{ public $ming,$id,$payload,$nothing;function __construct($iii){$this->ming$ii…

分布式链路追踪实战篇-日志库集成opentelemetry的思路

由上文分布式链路追踪入门篇-基础原理与快速应用可以知道分布式链路追踪的作用&#xff0c;但是距离应用到项目中&#xff0c;我们还需要对项目中一些关键组件进行opentelemetry的集成&#xff0c;例如日志库&#xff0c;ORM、http框架、rpc框架等。 一、日志库如何集成opentel…

实用高效 无人机光伏巡检系统助力电站可持续发展

近年来&#xff0c;我国光伏发电行业规模日益壮大&#xff0c;全球领先地位愈发巩固。为解决光伏电站运维中的难题&#xff0c;浙江某光伏电站与复亚智能达成战略合作&#xff0c;共同推出全自动无人机光伏巡检系统&#xff0c;旨在提高发电效率、降低运维成本&#xff0c;最大…

网站监控有什么用,什么是网站监控?

网站内容监控是指采用数据采集、人工智能、云计算、机器学习、语义分析等技术&#xff0c;结合网站内容监管指标&#xff0c;针对网站内容安全、信息发布、办事服务、互动交流、功能设计、创新发展等指标进行实时监测&#xff0c;以防止网站页面内容被篡改&#xff0c;出现黄、…

动态规划学习——子序列问题

目录 ​编辑 一&#xff0c;最长定差子序列 1.题目 2&#xff0c;题目接口 3&#xff0c;解题思路及其代码 一&#xff0c;最长定差子序列 1.题目 给你一个整数数组 arr 和一个整数 difference&#xff0c;请你找出并返回 arr 中最长等差子序列的长度&#xff0c;该子序列…

DS图_传递信息

Description 小明在和他的小伙伴们玩传消息游戏&#xff0c;游戏规则如下&#xff1a; 1. 有n名玩家&#xff0c;所有玩家编号分别为0~n-1&#xff0c;其中小明编号为0&#xff1b; 2. 每个玩家都有固定的若干个可传信息的其他玩家(也可能没有)。传消息的关系是单向的(即&am…

C在国内就业已经拉胯,ChatGPT告诉我的

文章目录 一、前言二、ChatGPT查到的数据三、数据亮点 1.C语言近3年数据大跌2.招聘数量每年都在剧增的是全栈工程师3.薪资涨幅最高的是全栈和网安 四、结语 一、前言 不仅前在微信群里搭建了一个ChatGPT 5.0做智能助手&#xff0c;让他来帮我回答群问题&#xff0c; 搭建好…

深度探究数据要素市场,企业为什么要参与数据资产化建设

我国正在发展数字经济&#xff0c;培育数字要素市场&#xff0c;推进数据市场化。在十四五数字经济发展规划中就已经将数据要素列为数字经济深化发展的核心引擎。今天和大家分享关于数据要素的前世今生&#xff0c;您将了解以下知识点&#xff1a; 1.什么是数据要素&#xff1f…

竞赛选题 题目:基于FP-Growth的新闻挖掘算法系统的设计与实现

文章目录 0 前言1 项目背景2 算法架构3 FP-Growth算法原理3.1 FP树3.2 算法过程3.3 算法实现3.3.1 构建FP树 3.4 从FP树中挖掘频繁项集 4 系统设计展示5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于FP-Growth的新闻挖掘算法系统的设计与实现…

预制菜产业发展背景下,如何利用视频监控保障行业监管工作

一、方案背景 随着社会的快速发展和人们生活水平的提高&#xff0c;预制菜产业作为现代餐饮行业的重要组成部分&#xff0c;越来越受到消费者的欢迎。然而&#xff0c;由于相关监管工作的不健全或不到位&#xff0c;一些问题也相继浮现出来&#xff0c;如&#xff1a;食品安全…

Windows从源码构建tensorflow

由一开始的在线编译&#xff0c;到后面的离线编译&#xff0c;一路踩坑无数。在此记录一下参考过的文章&#xff0c;有时间整理一下踩坑记录。 一、环境配置 在tensorflow官网上有版本对应关系 win10 bazel 3.1.0 msys2 tensorflow2.3.0 python3.5-3.8 MSVC2019 protobuf3.9.…

uniapp IOS从打包到上架流程(详细简单) 原创

​ 1.登入苹果开发者网站&#xff0c;打开App Store Connect ​ 2.新App的创建 点击我的App可以进入App管理界面&#xff0c;在右上角点击➕新建App 即可创建新的App&#xff0c;如下图&#xff1a; ​ 3.app基本信息填写 新建完App后&#xff0c;需要填写App的基本信息&…

3ds Max 电脑配置建议 | 建模+渲染选专业显卡or游戏显卡?

&#xfeff;使用3ds Max进行建模和渲染时&#xff0c;选择合适的电脑配置非常重要。比如在硬件选择上&#xff0c;究竟选购游戏显卡还是专业显卡呢&#xff1f;本文将为你详细介绍游戏显卡和专业显卡的区别&#xff0c;并提供配置建议&#xff0c;助你作出明智的决策。 &#…

NX二次开发UF_CSYS_set_origin 函数介绍

文章作者&#xff1a;里海 来源网站&#xff1a;https://blog.csdn.net/WangPaiFeiXingYuan UF_CSYS_set_origin Defined in: uf_csys.h int UF_CSYS_set_origin(tag_t csys_tag, double origin [ 3 ] ) overview 概述 Set origin of coordinate system. Note that this fu…

电视盒子哪款好?工程师整理双12超值电视盒子排名

因工作关系每天都会拆机、维修电视盒子&#xff0c;对电视盒子行业有着深入研究&#xff0c;双十二临近不少朋友问我电视盒子怎么挑选最值&#xff1f;我整理了目前市面上最超值的电视盒子排名&#xff0c;跟着我一起看看双十二挑电视盒子哪款好吧。 1.泰捷WEBOX WE40S电视盒子…

视频监控中的智能算法与计算机视觉技术

智能视频监控是一种基于人工智能技术的监控系统&#xff0c;它能够通过对图像和视频数据进行分析&#xff0c;自动识别目标物体、判断其行为以及进行异常检测等功能&#xff0c;从而实现对场景的智能化监管。以下是常见的一些用于智能视频监控的算法&#xff1a; 1、人脸识别技…

RabbitMq使用与整合

MQ基本概念 MQ概述 MQ全称 Message Queue&#xff08;[kjuː]&#xff09;&#xff08;消息队列&#xff09;&#xff0c;是在消息的传输过程中保存消息的容器。多用于分布式系统之间进行通信。 &#xff08;队列是一种容器&#xff0c;用于存放数据的都是容器&#xff0c;存…

C#关键字、特性基础及扩展合集(持续更新)

一、基础 Ⅰ 关键字 1、record record&#xff08;记录&#xff09;&#xff0c;编译器会在后台创建一个类。支持类似于结构的值定义&#xff0c;但被实现为一个类&#xff0c;方便创建不可变类型&#xff0c;成员在初始化后不能再被改变 &#xff08;C#9新增&#xff09; …

虽不想承认,但这就是CSGO游戏搬砖行业的现状

CSGO搬砖日常出货更新 其实整个搬砖市场&#xff0c;现在已经变得乌烟瘴气&#xff0c;散发着“恶臭”。我个人非常鄙视那些虚有其表&#xff0c;大小通吃的做法&#xff0c;那些甚至连搬砖数据都看不懂的人&#xff0c;也出来吹嘘着“实力强大&#xff0c;经验丰富”。这个世界…