华为OD机试 2025B卷题库疯狂收录中,刷题点这里
专栏导读
本专栏收录于《华为OD机试真题(Python/JS/C/C++)》。
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新。
一、题目描述
两端通过TLV格式的报文来通信,现在收到对端的一个TLV格式的消息包,要求生成匹配后的(tag,length,valueOffset)列表。
具体要求如下:
- 消息包中多组tag,length,value紧密排列,其中tag,length各种1字节(uint8_t),value所占字节数等于length的值。
- 结果数组中tag值已知,需要田中每个tag对应数据的length和valueOffset值(valueOffset为value在原消息包中的起始偏移量(从0开始,以字节为单位)),即将消息包中的tag与结果数组中的tag进行匹配(可能存在匹配失败的情况,若结果数组中tag在消息包中找不到,则length和valueOffset都为0)。
- 消息包和结果数组职工的tag值都按升序排序,且不重复。
- 此消息包未被篡改,但尾部可能不完整,不完整的一组TLV请丢弃掉。
二、输入描述
第一行:一个字符,代表收到的消息包。字符串长度在10000以内。
- 说明1:字符串使用十六进制文本格式(字母为大写)来展示消息包的数据,如0F04ABABABAB代表一组TLV:前两个字符(OF)代表tag值为15,接下来两个字符(04)代表length值为4字节,接下来8个字符即为4字节的value。
- 说明2:输入字符串中,每一组TLV紧密排列,中间无空格等分隔符
第二行:需要匹配的tag数量n(0 < n < 1000)
后面N行:需要匹配n个tag值(十进制表示),递增排列。
三、输出描述
和需要匹配的n个tag对应的n行匹配结果,每一行由长度和偏移量组成。
四、测试用例
测试用例1:
1、输入
0F04ABABABAB0E02CDCD
2
14
15
2、输出
2 8
4 2
3、说明
标签15(0F)长度4,valueOffset=2
标签14(0E)长度2,valueOffset=8
测试用例2:
1、输入
0A03ABC0F04DEDE
2
10
16
2、输出
3 2
0 0
3、说明
标签10(0A)存在,长度3,valueOffset=2
标签16(10)不存在,输出0 0
五、解题思路
- 第一行:一个字符,代表收到的消息包;
- 第二行:需要匹配的tag数量n(0 < n < 1000);
- 后面N行:需要匹配n个tag值(十进制表示),递增排列;
- 定义哈希表,存储tag对应的length和valueOffset;
- 解析字符串msg,初始化哈希表;
- 将16进制字符串转换为整数;
- 计算valueOffset;
- 跳过value,更新i;
- 如果i超出msg长度,跳出循环;
- 将tag、length、valueOffset存入tagMap中;
- 遍历tags,输出匹配结果。
六、Python算法源码
# Python 版本
import sys
def main():
import sys
# 读取输入
msg = sys.stdin.readline().strip() # 收到的消息包
n = int(sys.stdin.readline()) # 需要匹配的tag数量
tags = []
for _ in range(n):
tags.append(int(sys.stdin.readline())) # 读取需要匹配的tag值
tag_map = {} # 定义字典,存储tag对应的length和valueOffset
i = 0 # 初始化索引
while i + 4 <= len(msg): # 确保有完整的tag和length
tag_str = msg[i:i+2] # 获取tag的十六进制字符串
len_str = msg[i+2:i+4] # 获取length的十六进制字符串
tag = int(tag_str, 16) # 将tag转换为整数
length = int(len_str, 16) # 将length转换为整数
value_offset = (i + 4) // 2 # 计算value的起始偏移量
# 检查是否有足够的字符表示value
if i + 4 + length * 2 > len(msg):
break # 不完整的一组TLV,丢弃
tag_map[tag] = (length, value_offset) # 存入字典
i += 4 + length * 2 # 跳过当前TLV
for tag in tags:
if tag in tag_map:
length, value_offset = tag_map[tag]
print(f"{length} {value_offset}") # 输出length和valueOffset
else:
print("0 0") # 标签不存在,输出0 0
if __name__ == "__main__":
main()
七、JavaScript算法源码
// JavaScript 版本
const readline = require('readline');
function main() {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
let input = [];
rl.on('line', (line) => {
input.push(line.trim());
});
rl.on('close', () => {
let idx = 0;
const msg = input[idx++]; // 收到的消息包
const n = parseInt(input[idx++]); // 需要匹配的tag数量
const tags = [];
for (let i = 0; i < n; i++) {
tags.push(parseInt(input[idx++], 10)); // 读取需要匹配的tag值
}
const tagMap = new Map(); // 定义Map,存储tag对应的length和valueOffset
let i_index = 0; // 初始化索引
while (i_index + 4 <= msg.length) { // 确保有完整的tag和length
const tagStr = msg.substring(i_index, i_index + 2); // 获取tag的十六进制字符串
const lenStr = msg.substring(i_index + 2, i_index + 4); // 获取length的十六进制字符串
const tag = parseInt(tagStr, 16); // 将tag转换为整数
const length = parseInt(lenStr, 16); // 将length转换为整数
const valueOffset = Math.floor((i_index + 4) / 2); // 计算value的起始偏移量
// 检查是否有足够的字符表示value
if (i_index + 4 + length * 2 > msg.length) {
break; // 不完整的一组TLV,丢弃
}
tagMap.set(tag, [length, valueOffset]); // 存入Map
i_index += 4 + length * 2; // 跳过当前TLV
}
// 遍历tags,输出匹配结果
for (const tag of tags) {
if (tagMap.has(tag)) {
const [length, valueOffset] = tagMap.get(tag);
console.log(`${length} ${valueOffset}`);
} else {
console.log("0 0");
}
}
});
}
main();
八、C算法源码
/* C 版本 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// 定义最大标签数量
#define MAX_TAGS 1000
// 定义最大TLV数量
#define MAX_TLV 5000
typedef struct {
int tag;
int length;
int valueOffset;
} TLV;
int main() {
char msg[10001];
scanf("%s", msg); // 读取消息包
int n;
scanf("%d", &n); // 读取需要匹配的tag数量
int tags[MAX_TAGS];
for(int i = 0; i < n; i++) {
scanf("%d", &tags[i]); // 读取需要匹配的tag值
}
TLV tlvs[MAX_TLV];
int tlvCount = 0;
int i_index = 0;
int msg_len = strlen(msg);
while(i_index + 4 <= msg_len && tlvCount < MAX_TLV) { // 确保有完整的tag和length
char tagStr[3];
char lenStr[3];
strncpy(tagStr, msg + i_index, 2);
tagStr[2] = '\0';
strncpy(lenStr, msg + i_index + 2, 2);
lenStr[2] = '\0';
int tag = (int)strtol(tagStr, NULL, 16); // 转换tag
int length = (int)strtol(lenStr, NULL, 16); // 转换length
int valueOffset = (i_index + 4) / 2; // 计算valueOffset
// 检查是否有足够的字符表示value
if(i_index + 4 + length * 2 > msg_len) {
break; // 不完整的一组TLV,丢弃
}
tlvs[tlvCount].tag = tag;
tlvs[tlvCount].length = length;
tlvs[tlvCount].valueOffset = valueOffset;
tlvCount++;
i_index += 4 + length * 2; // 跳过当前TLV
}
// 对每个查询标签进行查找
for(int i = 0; i < n; i++) {
int found = 0;
for(int j = 0; j < tlvCount; j++) {
if(tags[i] == tlvs[j].tag) {
printf("%d %d\n", tlvs[j].length, tlvs[j].valueOffset);
found = 1;
break;
}
}
if(!found) {
printf("0 0\n");
}
}
return 0;
}
九、C++算法源码
/* C++ 版本 */
#include <bits/stdc++.h>
using namespace std;
int main(){
string msg;
cin >> msg; // 读取消息包
int n;
cin >> n; // 读取需要匹配的tag数量
vector<int> tags(n);
for(int &tag : tags){
cin >> tag; // 读取需要匹配的tag值
}
// 使用vector存储TLV信息
struct TLV {
int tag;
int length;
int valueOffset;
};
vector<TLV> tlvs;
int i = 0;
int msg_len = msg.length();
while(i + 4 <= msg_len){
string tagStr = msg.substr(i, 2); // 获取tag的十六进制字符串
string lenStr = msg.substr(i + 2, 2); // 获取length的十六进制字符串
int tag = stoi(tagStr, nullptr, 16); // 转换tag
int length = stoi(lenStr, nullptr, 16); // 转换length
int valueOffset = (i + 4) / 2; // 计算valueOffset
// 检查是否有足够的字符表示value
if(i + 4 + length * 2 > msg_len){
break; // 不完整的一组TLV,丢弃
}
tlvs.push_back(TLV{tag, length, valueOffset});
i += 4 + length * 2; // 跳过当前TLV
}
// 对每个查询标签进行查找
for(auto tag : tags){
bool found = false;
for(auto &tlv : tlvs){
if(tlv.tag == tag){
cout << tlv.length << " " << tlv.valueOffset << "\n";
found = true;
break;
}
}
if(!found){
cout << "0 0\n";
}
}
return 0;
}
🏆下一篇:华为OD机试真题 - 简易内存池(Python/JS/C/C++ 2025 B卷 200分)
🏆本文收录于,华为OD机试真题(Python/JS/C/C++)
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新。