【华为OD题库-015】报文重排序-Java

题目

对报文进行重传和重排序是常用的可靠性机制,重传缓冲区内有一定数量的子报文,每个子报文在原始报文中的顺序已知,现在需要恢复出原始报文。
输入描述
输入第一行为N,表示子报文的个数,0<N <= 1000。
输入第二行为N个子报文,以空格分开,子报文格式为字符串报文内容+后缀顺序索引,字符串报文内容由(a-Z ,A-Z)组成。后缀为整形值,表示顺序。顺序值唯一 ,不重复。
输出描述:
输出恢复出的原始报文。按照每个子报文的顺序值的升席排序,顺序后缀需要从恢复出的报文中删除掉
用例1
输入:
rolling3 stone4 like1 a2
输出:
like a rolling stone
说明:
4个子报文的内容分别为roling,stone,like,a,顺序值分别为3, 4,1, 2,按照顺序值升序并删除掉顺序后缀得到恢复的原始报文:
like a rolling stone
用例2
输入:
Lgifts6 and7 Exchanging1 all2 precious5 things8 kinds3 of4
注:这里需要注意and7与Exchanging1有两个空格
输出:
Exchanging all kinds of precious gifts and things

思路

这道题本身不难。大概经过下面3步,即可得到答案。

  1. 将输入的字符串根据空格拆分为字符串数组
  2. 遍历数组,对于每一个字符串,找到其第一个数字的索引位置,根据该位置拆分为字符串和顺序值,存入map中(将顺序值作为key,字符串作为val存放)
  3. 再遍历hashmap,可以直接获得恢复出的原始报文(按照顺序值的从小到大顺序)
    问题的关键在于理解,当hashmap中的key为integer时,map自己就是按照从小到大的顺序排序的当然,这需要在一定约束条件下,下面详细分析。
    这需要从hashmap的存放逻辑说起。下图是hashmap的逻辑结构。
    在这里插入图片描述
    通过上图,可以看到hashmap是由数组、链表+红黑树构成。默认情况下,hashmap的初始容量为16,也就是数组个数为16个。
    当存放的元素个数大于16 * 0.75(负载因子)时,hashmap会触发扩容操作(原来的2倍,即16扩成32)。
    再来看hashmap存放键的逻辑(key类型为Integer),即put(key,val)到底怎么做的?
    通过源码很容易找到下述逻辑:
    public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }
    static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

hashmap是通过hash(key)计算存放位置的,而hash函数是返回的key的hashcode和其右移16位的的异或值。比如key值是16,那么其hashcode为16(Integer类型的hashcode返回其本身)。再通过异或计算得到的值还是为16.计算过程如下:
0000 0000 0001 0000 ^ //16的二进制表示
0000 0000 0000 0000 //右移16位,全为0。右移的原因是,可以让最后结果含有hashcode高16位的特征,使其在hashmap中存放得更均匀。
=0000 0000 0001 0000 //还是得到了16
上面通过hash函数(有人称扰动函数)获得了16,接下来看看怎么利用16计算其在hashmap的位置的(即存放hashmap数组的哪个索引?)
在这里插入图片描述
如上图所示,只关注圈出来的部分。计算位置i的方式为:i=(n - 1) & hash,其中n为当前hashmap的容量,hash为上一步hash(key)计算出来的值。所以当hash=16时,位置i=(16-1)&16=0。也就是在索引0处存放值。计算过程如下:
0000 1111 & //16-1=15的二进制表示
0001 0000 //16的二进制表示
=0000 0000 //结果为0,其实就是16%16的值。这也是为什么容量要设置为2的整数次幂的原因,因为对n等于2的整数次幂来说。x&(n-1)=x%n
结合上面的描述,我们用个具体实例来演示下hashmap的存放过程。
在这里插入图片描述

通过上面的过程,可以看到,在hashMapkey为Integer时,在一定条件下,可以直接按照key的从小到大的顺序输出。比如上面的步骤3,输出结果是0,2。步骤6输出结果是:0 2 3 4 5 6 7 8 9 10 11 16 17。但是步骤4输出的结果为:0 16 2。
现在需要考虑什么时候不能正确排序?显然,当hashmap不扩容时,输入的key又不小于当前容量时,会造成某个节点存放多个值,最后无法按照从小到大的顺序输出。
但是就我们这道题目来说,输入的数据范围只能是1~n这样连续的数字,n<=1000。不设置hashmap初始容量的情况下,hashmap的容量扩容过程应该为:16 32 64 128 256 1024。通过不断扩容最终不会存在某个节点有多个值的情况,所以可以按照key值从小到大的顺序输出。当然扩容不可避免的降低了效率。因为我们知道字符串的总量。我们可以在初始化hashmap时直接指定容量大小(不必我们自己计算为2的整数次幂,hashmap会自动完成这个操作)。
在这里插入图片描述

题解

package hwod;

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class MessageSort {
    static Map<Integer, String> map;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        sc.nextLine();
        map = new HashMap<>(N);

        String[] inputs = sc.nextLine().split("\\s+");
        System.out.println(messageSort(inputs));
    }

    private static String messageSort(String[] inputs) {

        for (int i = 0; i < inputs.length; i++) {
            int idx = getFirstNum(inputs[i]);
            int num = Integer.parseInt(inputs[i].substring(idx));
            String val = inputs[i].substring(0, idx);
            map.put(num, val);
        }
        StringBuilder sb = new StringBuilder();
        //可以直接遍历map(key为Interger的hashmap在一定条件下可以按照key的从小到大排序)
        //也可以遍历1~N,直接取map.get(1)、map.get(2)……这样就不用利用上面分析的hashmap的特性了。
        for (Integer k : map.keySet()) {
            if (sb.length() != 0) {
                sb.append(" ");
            }
            sb.append(map.get(k));
        }
        return sb.toString();
    }

    private static int getFirstNum(String input) {
        char[] chars = input.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            if (Character.isDigit(chars[i])) {
                return i;
            }
        }
        return -1;
    }
}

推荐

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

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

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

相关文章

安防监控EasyCVR视频汇聚平台运维现场无法使用Linux抓包该如何解决?

视频云存储/安防监控EasyCVR视频汇聚平台基于云边端智能协同&#xff0c;支持海量视频的轻量化接入与汇聚、转码与处理、全网智能分发、视频集中存储等。监控视频平台EasyCVR拓展性强&#xff0c;视频能力丰富&#xff0c;具体可实现视频监控直播、视频轮播、视频录像、云存储、…

竞赛选题 深度学习的口罩佩戴检测 - opencv 卷积神经网络 机器视觉 深度学习

文章目录 0 简介1 课题背景&#x1f6a9; 2 口罩佩戴算法实现2.1 YOLO 模型概览2.2 YOLOv32.3 YOLO 口罩佩戴检测实现数据集 2.4 实现代码2.5 检测效果 3 口罩佩戴检测算法评价指标3.1 准确率&#xff08;Accuracy&#xff09;3.2 精确率(Precision)和召回率(Recall)3.3 平均精…

“大学生”返乡投身乡村建设,直播电商成为返乡创业新潮流!

数字乡村建设是新时代乡村振兴的必经之路&#xff0c;它是伴随网络化、信息化和数字化在农业农村经济社会发展中的应用&#xff0c;以及农民现代信息技能的提高而内生的农业农村现代化发展和转型进程&#xff0c;既是乡村振兴的战略方向&#xff0c;也是建设数字中国的重要内容…

vue3使用时遇到的问题

使用elementplus遇到的问题 1.el-form中input无法输入 问题描述&#xff1a;在el-form中的el-input中输入数字或字母时出现卡顿&#xff0c;输入不进去的现象 问题原因&#xff1a;el-form的ref和model的名称写成了一样的单词 问题解决&#xff1a;两个不能一样 2.input去除…

CTFhub-RCE-php://input

我们需要使用php://input来构造发送的指令 查看phpinfo&#xff0c;找到一下字段 证明是可以使用php://input 1. 使用Burpsuite抓包并转至Repeater 2. 构造包 方法&#xff1a;POST 目标&#xff1a;/?filephp://input Body&#xff1a;<?php system("ls /"…

约束条件的安全测试_报错注入

约束条件的安全测试_报错注入 基于约束的SQL攻击 报错注入

(附源码)基于SSM旅行社网站-计算机毕设 90030

SSM旅行社网站 摘 要 旅游业是一个信息密集型产业&#xff0c;传统的旅游景点门票售卖受到技术和人力的限制&#xff0c;旅行社网站则可以建立景区与游客之间的有效通道&#xff0c;能更好的满足游客便捷旅游的需求。旅行社网站的设计是基于SSM框架、Mysql数据库、JSP技术、Aja…

wireshark打开tcpdump抓的包 vwr: Invalid data length runs past the end of the record

tcpdump -i any -n -s0 > t.pcap 使用此命令在Debian系统上抓包&#xff0c;下载到PC&#xff0c;用wireshark打开时报错&#xff1a; 后来发现写入文件时使用 -w 是没问题的&#xff0c;原因还不清楚。 tcpdump -i any -n -s0 -w t.pcap

Mysql-数据类型

1.数据类型分类 2. 整形类型 说明 : 在MySQL中&#xff0c;整型可以指定是有符号的和无符号的&#xff0c;默认是有符号的。可以通过UNSIGNED来说明某个字段是无符号的。 注意&#xff1a;尽量不使用unsigned&#xff0c;对于int类型可能存放不下的数据&#xff0c;int unsign…

7个好用的可视化数据平台,让你的数据分析更高效率、高逼格

在信息爆炸的时代&#xff0c;数据是企业决策的重要依据。为了更高效率、更高逼格地进行数据分析&#xff0c;选择一个优秀的可视化数据平台至关重要。在众多可选项中&#xff0c;VeryReport报表软件脱颖而出&#xff0c;成为最好用的可视化数据平台之一&#xff0c;以下是其突…

Pyside6/PYQT6如何实现无边框设计,解决无边框窗口无法移动和实现窗口拖拽改变大小的问题

文章目录 💢 问题 💢💯 解决方案 💯🍔 准备工作📚 setWindowFlags、setWindowFlag和setAttribute的区别🐾 操作步骤🐾 窗口无边框🐾 窗口透明🐾 实现窗口可移动🐾 实现窗口拖拽改变大小⚓️ 相关链接 ⚓️💢 问题 💢 有时候我们需要一个无边框的UI设…

活跃类指标

活跃类指标反映了用户的真实使用情况。本节我们深入探讨活跃类指标的核心逻辑。 1&#xff0e; UV UV ( Unique Visitor &#xff0c;独立访客&#xff09;&#xff0c;是所有活跃类指标的基础。 既然叫独立访客&#xff0c;何谓之独立&#xff1f; APP 产品界定独立访客相对…

如何用postman+jmeter实现接口实例

一、接口基础 为什么要单独测试接口&#xff1f; 1. 程序是分开开发的&#xff0c;前端还没有开发&#xff0c;后端已经开发完了&#xff0c;可以提前进入测试 2. 接口直接返回的数据------越底层发现bug&#xff0c;修复成本是越低的 3. 接口测试能模拟功能测试不能测到的异…

2.2 Windows驱动开发:内核自旋锁结构

提到自旋锁那就必须要说链表&#xff0c;在上一篇《内核中的链表与结构体》文章中简单实用链表结构来存储进程信息列表&#xff0c;相信读者应该已经理解了内核链表的基本使用&#xff0c;本篇文章将讲解自旋锁的简单应用&#xff0c;自旋锁是为了解决内核链表读写时存在线程同…

医院等级评审,离不开医院不良事件报告系统

医院不良事件报告系统全套源码 不良事件管理系统源码 不良事件上报系统对事件的报告、处置、跟踪、评价、分析、改进、学习等进行了综合管理&#xff0c;通过双向互评机制实现临床科室与职能部门之间的进一步互动&#xff0c;加强不良事件报告处置过程中的信息互通能力。 围绕…

项目生命周期分享

第一阶段&#xff1a; 项目启动&#xff0c;2天时间即可&#xff0c;需要输出项目进度计划 1.项目组成立1天&#xff0c;用来建立项目组&#xff0c;确定工作分工和工作方法&#xff0c;指定项目总体计划&#xff08;包括前期交流&#xff0c;需求收集&#xff0c;项目立项等…

数组区域检索的优化 --- 分块,线段树,树状数组

思考 首先让我们来思考一个问题&#xff0c;给定一个数组&#xff0c;和left与right的值&#xff0c;让你求这个数组中left到right之间元素的和&#xff0c;你会怎么计算&#xff1f;最简单的当然是遍历。如果有人问你这个问题的时候&#xff0c;他决对是会让你优化的&#xff…

vue项目路由使用history模式,nginx配置,刷新页面显示404

需要在配置项中添加 try_files $uri $uri/ /index.html;

削峰填谷:居民小区电动汽车有序充电策略研究

摘 要&#xff1a;针对电动汽车在居民小区无序充电对电网系统产生严重隐患及充电间时过长问题&#xff0c;提出一种采用延迟充电的电动汽车有序充电控制策略&#xff0c;并在分析国内外电动汽车有序充电的研究现状后&#xff0c;设计了居民小区电动汽车有序充电策略的总体框架。…

【源码复现】图神经网络之PPNP/APPNH

目录 1、论文简介2、论文核心介绍2.1、现有方法局限2.2、PageRank&Personalized PageRank2.3、PPNP&APPNP 3、源码复现3.1、模型总体框架3.2、PPNP3.3、APPNP3.4、MLP(两层) 1、论文简介 论文题目——《PREDICT THEN PROPAGATE: GRAPH NEURAL NETWORKS MEET PERSONALI…