• 【华为OD机考B卷 | 100分】整数编码(JAVA题解——也许是全网最详)


    前言

    本人是算法小白,甚至也没有做过Leetcode。所以,我相信【同为菜鸡的我更能理解作为菜鸡的你们的痛点】。

    题干

    1. 题目描述

    实现一种整数编码方法,使得待编码的数字越小,编码后所占用的字节数越小。
    编码规则如下

    1. 编码时7位一组,每个字节的低7位用于存储待编码数字的补码
    2. 字节的最高位表示后续是否还有字节,置1表示后面还有更多的字节,置0表示当前字节为最后一个字节
    3. 采用小端序编码,低位和低字节放在低地址上
    4. 编码结果按16进制数的字符格式输出,小写字母需转换为大写字母

    2. 输入描述

    输入的为一个字符串表示的正整数

    3. 输出描述

    输出一个字符串,表示整数编码的16进制码流

    4. 示例

    示例1:

    输入0
    输出00
    说明输出的16进制字符,不足2位的前面补0。如00,01,02

    示例2:

    输入100
    输出64
    说明100的二进制表示为01100100,只需要一个字节进行编码;
    字节的最高位置0,剩余7位存储数字100的低7位(1100100),所以编码后的输出为64

    示例3:

    输入1000
    输出E807
    说明1000的二进制表示为001111101000,至少需要两个字节进行编码;
    第一个字节最高位置1,剩余的7位存储数字1000的第一个低7位(1101000),所以第一个字节的二进制为1110 1000,即E8;
    第二个字节最高位置0,剩余的7位存储数字1000的第二个低7位(00111)(高位补2个0,填满7位,得:0000111),所以第二个字节的二进制为0000 0111,即07;
    采用小端序编码,所以低字节E8输出在前,高字节07输出在后。

    解答

    遇到的问题

    有了前一次经验,在本次解题过程中没有遇到什么理解上的困难了,但是出现了生僻API的使用困难。如下:

    1. 补码怎么得到?(后来回想起:正数的补码就是原码)
    2. 怎么得到当前数的二进制数?(Integer/Long包装类提供了)
    3. 怎么输出十六进制数?(Integer/Long包装类提供了)
    4. 怎么得到低7位?也许还有的朋友甚至不知道低7位,高位是什么意思(字符串截取)

    低n位:从右往左数的n个二进制位
    高n位:从左往右数的n个二进制位

    解题思路

    本次题干的要求其实已经写在了题目描述上,根据题干凝练一下过程就好:

    1. 首先读取一个正整数,获取该正整数的补码,即:二进制原码(正数的补码跟原码相同)
    2. 以7位为单位,循环截取该补码的低7位。如果截取前的字符串长度>7,则在截取字符串的最前面补1,反之补0
    3. 输出当前二进制码对应的十六进制码,若十六进制数长度不足2位,则在前面补0。最后将结果返回出去,再用StringBuilder累加起来

    代码示例

    public class IntegerEncoder {
    
        /**
         * 每次编码的位数
         */
        static final int ENCODER_LENGTH = 7;
    
        public static void main(String[] args) {
    
            // 步骤1:读正整数,取补码
            Scanner scanner = new Scanner(System.in);
            int inputInt = scanner.nextInt();
            String binaryStr = getCompletmentStr(inputInt);
            StringBuilder result = new StringBuilder();
    
            // 拼凑结果
            for (int endIndex = binaryStr.length(); endIndex > 0; endIndex -= ENCODER_LENGTH) {
    
                // 步骤2:循环截取该补码的低7位
                int startSubstringIndex = Math.max(endIndex - ENCODER_LENGTH, 0);
                String lower7Bits = binaryStr.substring(startSubstringIndex, endIndex);
    
                // 处理高1位的值
                char highBit = (endIndex > ENCODER_LENGTH) ? '1' : '0';
                String newBinaryStrAfterEncoder = highBit + lower7Bits;
    
                // 步骤3:获取当前二进制码对应的十六进制码
                String hexStr = toHexStr(newBinaryStrAfterEncoder);
                result.append(hexStr);
            }
    
            System.out.println("整数编码后的结果:" + result);
        }
    
        /**
         * 获取指定正整数的补码
         *
         * @param nums 指定整数
         * @return 整数的补码字符串
         */
        private static String getCompletmentStr(int nums) {
            return Integer.toBinaryString(nums);
        }
    
        /**
         * 将新的字符串代表的二进制数转换成十六进制字符串
         *
         * @param newNumsStr 新数的二进制数
         * @return 十六进制字符串
         */
        private static String toHexStr(String newNumsStr) {
            int newNums = Integer.parseInt(newNumsStr, 2);
            String hexString = Integer.toHexString(newNums);
            if (hexString.length() == 1) {
                hexString = "0" + hexString;
            }
            return hexString.toUpperCase();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    代码解读:
    我将解题思路中关键的3个步骤,都在代码注释中标明了。也许大家会比较陌生的是以下几点:

    1. Integer包装类提供的获取二进制数,以及获取十六进制数的api(毕竟不常用)
    2. 循环截取低7位的操作使用了String.subString(start, end)这个api。并且,循环使用了倒序跳跃的方式

    倒序体现在:从末尾开始遍历
    跳跃体现在:并非是一个一个字符串来遍历,而是每次想左挪动7位,即:endIndex -= 7

    1. Integer.parseInt(newNumsStr, 2)这个api也比较陌生。代码中第二个参数2表示是二进制
  • 相关阅读:
    含叠氮的代谢糖蛋白标记试剂361154-30-5,N -叠氮乙酰基甘露糖胺-四酰基化
    Java项目:SSM图书销售进销存管理系统
    JAVA计算机毕业设计舞蹈网站(附源码、数据库)
    一篇文章入门循环神经网络RNN
    win10蓝屏重启故障修复经验分享
    单点架构、集群架构、服务化架构、SOA、微服务到底有什么联系和关系?
    网工实验笔记:IPv6(配置6to4隧道)
    背课文记单词,读课文记单词,读文章记单词;40篇文章搞定3500词;71篇文章突破中考单词;15篇文章贯通四级词汇;15篇文章贯通六级词汇
    聊一聊前后端权限控制 RBAC(完整流程)
    室友打团太吵?一条命令断掉它的WiFi
  • 原文地址:https://blog.csdn.net/qq_32681589/article/details/133668928