• 华为OD机考算法题:TLV解码


    目录

    题目部分

    解析与思路

    代码实现


    题目部分

    题目TLV编码
    难度
    题目说明TLV编码是按 [Tag Length Value] 格式进行编码的,一段码流中的信元用 Tag 标识,Tag 在码流中唯一不重复,Length 表示信元Value的长度,Value 表示信元的值。
    码流以某信元的 Tag 开头,Tag 固定占一个字节,Length 固定占两个字节,字节序为小端序。
    现给定 TLV 格式编码的码流,以及需要解码的信元 Tag,请输出该信元的 Value。
    输入码流的 16 机制字符中,不包括小写字母,且要求输出的 16 进制字符串中也不要包含小写字母;码流字符串的最大长度不超过 50000 个字节。
    输入描述输入的第一行为一个字符串,表示待解码信元的 Tag;
    输入的第二行为一个字符串,表示待解码的 16 进制码流,字节之间用空格分隔。
    输出描述输出一个字符串,表示待解码信元以 16 进制表示的 Value。
    补充说明

    ---------------------------------------------------------------------------------------

    示例
    示例1
    输入31
    32 01 00 AE 90 02 00 01 02 30 03 00 AB 32 31 31 02 00 32 33 33 01 00 CC
    输出32 33
    说明需要解析的信元的 Tag 是 31,从码流的起始处开始匹配,Tag 为 32 的信元长度为 1 (01 00,小端序表示为 1);
    第二个信元的 Tag 是 90,其长度为 2;
    第三个信元的 Tag 是 30,其长度为 3;
    第四个信元的 Tag 是 31,其长度为 2(02 00),所以返回长度后面的两个字节即可,即 32 33。

    解析与思路

    题目解读

    题目中,有两行输入。其中第二行是 TLV 信息流。TLV 信息流由多个信元组成,每个信元又由 Tag、Length、Value 组成;第一行是 Tag,即一个 TLV 信元的 Tag。

    题目要求从第二行的多个信元中,找到第一行的 Tag 所对应的信元。然后输出此信元的 Value。

    在输入示例中,第一行指定了信元的 Tag 是31,第二行输入的信息流包含了 5个 信元,依次为32、90、30、31、33。我们找到 Tag 为 31 的信元,它为 31 02 00 32 33,其中 31 是 Tag,02 00(即2)是长度,那么其紧跟的 2 个字节 32 33 为 Value,所以最终的结果输出为 32 33。

    分析与思路

    此题根据指定的 Tag,从信息流中找到对应的信息员,输出其 Value即可,并不涉及太复杂的逻辑算法。实现如下:

    1. 记录第一行输入的数字,设为变量 Tag。
    2. 逐一遍历第二行输入的信息流。遍历时,先判断第一个输入是否等于tag:

    • 如果等于 Tag,则继续遍历接下来的 2 个字节,(根据小端序)计算长度,设为变量 length,然后输出接下来的 length 个字节,即为最终输出。输出后退出程序。
    • 如果不等于 Tag,则继续遍历接下来的2个字节,计算长度,设为变量 length,然后跳过接下来的 length 个字节,然后继续步骤 2。

    此算法只需要遍历一次第二行的输入,时间复杂度为 O(n),只需要2个额外的辅助变量,空间复杂度为 O(1)。


    代码实现

    Java代码

    1. import java.util.Scanner;
    2. /**
    3. * TLV解码
    4. * @since 2023.09.04
    5. * @version 0.2
    6. * @author Frank
    7. *
    8. */
    9. public class LTV_Solution {
    10. public static void main(String[] args) {
    11. Scanner sc = new Scanner(System.in);
    12. while (sc.hasNext()) {
    13. // 第一行输入的tag
    14. String tag = sc.nextLine();
    15. // 第二行输入的TLV数据流
    16. String stream = sc.nextLine();
    17. String[] tlvStream = stream.split(" ");
    18. processLTVSolution( tag, tlvStream );
    19. }
    20. }
    21. private static void processLTVSolution( String tag, String tlvStream[] )
    22. {
    23. int i = 0;
    24. while (i < tlvStream.length) {
    25. String tagTmp = tlvStream[i];
    26. String lengthStr = tlvStream[i + 2] + tlvStream[i + 1];
    27. int length = Integer.parseInt(lengthStr, 16);
    28. // 已找到,输出
    29. if ( !tagTmp.equals( tag )) {
    30. // 没有找到Tag,略过,寻找下一个
    31. i += ( 3 + length);
    32. continue;
    33. }
    34. StringBuilder outputSB = new StringBuilder();
    35. for (int j = 0; j < length; j++) {
    36. outputSB.append(tlvStream[i + j + 3]);
    37. if (j != length - 1) {
    38. outputSB.append(" ");
    39. }
    40. }
    41. System.out.println(outputSB.toString());
    42. return;
    43. }
    44. }
    45. }

    JavaScript代码

    1. const rl = require("readline").createInterface({ input: process.stdin });
    2. var iter = rl[Symbol.asyncIterator]();
    3. const readline = async () => (await iter.next()).value;
    4. void async function() {
    5. while (line = await readline()) {
    6. // 第一行数据
    7. var tag = line;
    8. // 第二行数据转换成数组
    9. line = await readline();
    10. var ltvs = line.split(" ");
    11. processLTVSolution(tag, ltvs);
    12. }
    13. }();
    14. function processLTVSolution(tag, ltvs) {
    15. var i = 0;
    16. while (i < ltvs.length) {
    17. var tagTmp = ltvs[i];
    18. var lengthStr = ltvs[i + 2] + ltvs[i + 1];
    19. var length = parseInt(lengthStr, 16);
    20. // 没有找到Tag,略过,寻找下一个
    21. if (tagTmp != tag) {
    22. i += (3 + length);
    23. continue;
    24. }
    25. // 已找到,输出
    26. var output = "";
    27. for (var j = 0; j < length; j++) {
    28. output += (ltvs[i + j + 3]);
    29. if (j != length - 1) {
    30. output += " ";
    31. }
    32. }
    33. console.log(output);
    34. return;
    35. }
    36. }

    (完)

  • 相关阅读:
    Golang接口实现OCP原则
    CSDN每日一练 |『坐公交』『盗版解锁密码』『n边形划分』2023-09-17
    Educational Codeforces Round 133 (Rated for Div. 2)A.B
    Matlab如何提取论文插图中的渐变色?一招轻松搞定
    聊一聊对领域驱动设计中“领域”这个词语的理解与分析方法
    第147篇 笔记-预言机(Oracle)
    如何提高文章质量,不被发文助手“推荐受影响”
    Apache Doris的Bucket Shuffle Join实现
    Chapter10 : Deep Neural Networks for QSAR
    【C语言】32个关键字
  • 原文地址:https://blog.csdn.net/ZiJinShi/article/details/132668464