2024华为OD机试(E卷+D卷+C卷)最新题库【超值优惠】Java/Python/C++合集
题目描述
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编码格式的解析,利用小端序字节进行长度信息的转换,目标是从给定码流中提取出与目标Tag匹配的信元的Value值。这类问题可以归类为字节序处理与字符串匹配。
解题思路:
- TLV格式解析:TLV编码由Tag、Length、Value组成:
- Tag:信元标识符,固定占1个字节。
- Length:信元长度,固定占2个字节(小端序存储)。
- Value:信元值,长度由Length字段表示。
- 小端序处理:Length字段为小端序存储,需要将两个字节颠倒顺序再进行长度计算,即
Length = bytes[idx+2] + bytes[idx+1]
。- 匹配流程:
- 从码流的开头开始遍历Tag,如果找到与给定Tag相同的信元,则解析其后面的Length字节,计算Value部分并输出。
- 每个信元的解析长度为:
Tag(1字节) + Length(2字节) + Value(Length指定的字节数)
。- 遍历过程:
- 逐步解析Tag、Length和Value,直到找到与给定Tag匹配的信元,输出其对应的Value。
时间复杂度:每个信元的解析时间是O(1),遍历码流的整体复杂度为O(n),其中n是码流的长度。由于每次遍历都会跳过已解析的信元,因此整体时间复杂度是O(n)。
空间复杂度:除了输入数据外,额外使用的空间主要是存储结果的List或数组,空间复杂度为O(n)。
Java
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
/**
* @author code5bug
*/
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 待解码信元的Tag
String tag = in.next();
// 码流字符串
List<String> bytes = new ArrayList<>();
while (in.hasNext()) {
bytes.add(in.next());
}
List<String> result = new ArrayList<>();
int idx = 0, n = bytes.size();
while (idx < n) {
String t = bytes.get(idx);
// 将 16 进制字符串转成 10 进制整数
int len = Integer.parseInt(bytes.get(idx + 2) + bytes.get(idx + 1), 16);
// 待接码的元Tag的信元值解析存入 result 中
if (t.equals(tag)) {
result = bytes.subList(idx + 3, idx + 3 + len);
break;
}
idx += len + 3;
}
// 输出结果
System.out.println(String.join(" ", result));
}
}
Python
# 待解码信元的Tag
tag = input()
# 码流字符串
bytes = input().split()
result = []
idx, n = 0, len(bytes)
while idx < n:
t = bytes[idx]
# 将 16 进制字符串转成 10 进制整数
length_hex = bytes[idx + 2] + bytes[idx + 1]
length = int(length_hex, 16)
# 待接码的元Tag的信元值解析存入 result 中
if t == tag:
result = bytes[idx + 3:idx + 3 + length]
break
idx += length + 3
# 输出结果
print(" ".join(result))
C++
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main() {
// 待解码信元的Tag
string tag;
cin >> tag;
// 码流字符串
vector<string> bytes;
string byte;
while (cin >> byte) {
bytes.push_back(byte);
}
vector<string> result;
int idx = 0, n = bytes.size();
while (idx < n) {
string t = bytes[idx];
// 将 16 进制字符串转成 10 进制整数
int len = stoi(bytes[idx + 2] + bytes[idx + 1], nullptr, 16);
// 待接码的元Tag的信元值解析存入 result 中
if (t == tag) {
result.assign(bytes.begin() + idx + 3, bytes.begin() + idx + 3 + len);
break;
}
idx += len + 3;
}
// 输出结果
for (int i = 0; i < result.size(); i++) {
if (i != 0) cout << " ";
cout << result[i];
}
cout << endl;
return 0;
}
整理题解不易, 如果有帮助到您,请给点个赞 ❤️ 和收藏 ⭐,让更多的人看到。🙏🙏🙏