华为OD机试 - TLV格式(Python/JS/C/C++ 2025 B卷 100分)

在这里插入图片描述

华为OD机试 2025B卷题库疯狂收录中,刷题点这里

专栏导读

本专栏收录于《华为OD机试真题(Python/JS/C/C++)》

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新。

一、题目描述

两端通过TLV格式的报文来通信,现在收到对端的一个TLV格式的消息包,要求生成匹配后的(tag,length,valueOffset)列表。
具体要求如下:

  1. 消息包中多组tag,length,value紧密排列,其中tag,length各种1字节(uint8_t),value所占字节数等于length的值。
  2. 结果数组中tag值已知,需要田中每个tag对应数据的length和valueOffset值(valueOffset为value在原消息包中的起始偏移量(从0开始,以字节为单位)),即将消息包中的tag与结果数组中的tag进行匹配(可能存在匹配失败的情况,若结果数组中tag在消息包中找不到,则length和valueOffset都为0)。
  3. 消息包和结果数组职工的tag值都按升序排序,且不重复。
  4. 此消息包未被篡改,但尾部可能不完整,不完整的一组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

五、解题思路

  1. 第一行:一个字符,代表收到的消息包;
  2. 第二行:需要匹配的tag数量n(0 < n < 1000);
  3. 后面N行:需要匹配n个tag值(十进制表示),递增排列;
  4. 定义哈希表,存储tag对应的length和valueOffset;
  5. 解析字符串msg,初始化哈希表;
    • 将16进制字符串转换为整数;
    • 计算valueOffset;
    • 跳过value,更新i;
    • 如果i超出msg长度,跳出循环;
    • 将tag、length、valueOffset存入tagMap中;
  6. 遍历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算法的适用场景,发现新题目,随时更新。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哪 吒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值