【春招笔试】2025.05.12荣耀机考研发岗真题改编

✅ 春招备战指南 ✅

💡 学习建议:

  • 先尝试独立解题(建议用时:90分钟/套)
  • 对照解析查漏补缺

🧸 题面描述背景等均已深度改编,做法和题目本质基本保持一致。

🍹 感谢各位朋友们的订阅,你们的支持是我们创作的最大动力

🌸 目前本专栏已经上线60+套真题改编解析,后续会持续更新的

春秋招合集 -> 互联网必备刷题宝典🔗

题目一:智能网关报文加密挑战

1️⃣:解析十六进制字节流

2️⃣:根据特定规则进行字符转义处理

3️⃣:计算并输出处理后的报文

难度:中等

这道题目考察对特殊字符转义处理的实现,这是在通信协议中常见的操作。通过遍历输入报文并按照特定规则进行转义,可以实现高效的 O(n) 解法。主要难点在于正确处理十六进制输入输出以及准确计算转义后的报文长度。

题目二:古镇探秘最佳路线

1️⃣:创建动态规划数组记录最小路径和

2️⃣:正确初始化首行和首列

3️⃣:通过状态转移计算最优解

难度:中等

这道题目是经典的最小路径和问题,非常适合使用动态规划解决。通过分析从起点到各个位置的最小累计费用,并利用状态转移方程求解,可以得到一个时间复杂度为 O(M*N) 的高效解法,非常适合题目给定的数据范围。

题目三:音乐会座位分配问题

1️⃣:使用回溯算法枚举所有分配方案

2️⃣:递归处理每个学生的证书分配

3️⃣:生成并输出符合格式的分配方案

难度:中等

这道题目本质上是一个组合数学问题,考察将 n 个相同物品分配给 k 个不同容器的方案数及具体方案。使用回溯算法可以有效地生成所有可能的分配方案,时间复杂度为 O(n^k),对于题目给定的数据范围是可以接受的。

01. 智能网关报文加密挑战

问题描述

在现代物联网通信中,报文传输的安全性至关重要。小基 工程师正在开发一种用于智能家居网关的安全通信协议,其中包含一种特殊的报文加密技术。

该加密技术需要对原始报文进行特殊字符转义处理:当报文中出现 时,需要将其转义为 两个字节;当出现 时,需要将其转义为 两个字节;其他字节保持不变。

请你帮助 小基 工程师实现这个报文转义功能。

输入格式

第一行包含多个用空格分隔的十六进制数。

第一个数表示原始报文的长度(包含这个长度字节本身),不超过 。长度字节虽然算作报文的一部分,但不参与转义处理。

后续的数表示报文的每个字节,均为十六进制形式。

输出格式

输出一行用空格分隔的十六进制数,表示转义处理后的报文。

第一个数表示转义后报文的总长度(包含这个长度字节本身),不超过

所有输出的十六进制数都应转换为大写形式,不带 前缀。

样例输入

8 1 2 3 4 5 6 A

样例输出

9 1 2 3 4 5 6 12 34

数据范围

  • 原始报文长度(包括长度字节)不超过 字节
  • 转义后报文长度不超过 字节
  • 所有字节均为合法的十六进制数(
样例 解释说明
样例1 输入报文为 ,其中 表示报文长度。报文中 (十六进制 )需要转义为 ,其他字节保持不变。输出长度变为 ,内容为

题解

这道题目主要考察的是特殊字符转义处理,这是在通信协议中非常常见的操作。

首先,让我们理解题目要求:

  1. 我们需要处理一段十六进制报文
  2. 报文的第一个字节表示长度,不参与转义处理
  3. 需要将 0x0A 转义为 0x12 0x34
  4. 需要将 0x0B 转义为 0xAB 0xCD
  5. 其他字节保持不变
  6. 最后输出转义后的报文,第一个字节为新的长度

解题思路很直接:

  1. 读取输入报文
  2. 跳过第一个长度字节
  3. 对剩余字节进行遍历,根据转义规则生成新的报文
  4. 计算转义后的总长度
  5. 输出新的长度和转义后的报文

实现上主要需要注意:

  1. 正确处理十六进制输入和输出
  2. 确保输出的十六进制数为大写形式
  3. 正确计算转义后的报文长度

时间复杂度是 O(n),其中 n 是原始报文的长度。由于题目限制报文长度最大为 127 字节,所以这个解法是高效的。

参考代码

  • Python
import sys
input = lambda:sys.stdin.readline().strip()

# 处理报文转义
def proc():
    # 读取输入的十六进制报文
    line = input().split()
    res = []
    
    # 跳过长度字节,处理后续字节
    for i in range(1, len(line)):
        val = int(line[i], 16)  # 将十六进制字符串转为整数
        if val == 0x0A:  # 转义 0x0A
            res.append(0x12)
            res.append(0x34)
        elif val == 0x0B:  # 转义 0x0B
            res.append(0xAB)
            res.append(0xCD)
        else:  # 其他字节保持不变
            res.append(val)
    
    # 计算新的长度(包括长度字节本身)
    new_len = 1 + len(res)
    
    # 输出结果
    out = [new_len] + res
    print(' '.join([format(x, 'X') for x in out]))

if __name__ == "__main__":
    proc()
  • Cpp
#include <bits/stdc++.h>
using namespace std;

void esc() {
    // 读取输入的十六进制报文
    string s;
    getline(cin, s);
    istringstream iss(s);
    
    vector<int> nums;
    string val;
    
    // 跳过第一个长度字节
    iss >> val;
    
    // 读取剩余字节
    while (iss >> val) {
        nums.push_back(stoi(val, nullptr, 16));
    }
    
    // 处理转义
    vector<int> res;
    for (int v : nums) {
        if (v == 0x0A) {  // 转义 0x0A
            res.push_back(0x12);
            res.push_back(0x34);
        } else if (v == 0x0B) {  // 转义 0x0B
            res.push_back(0xAB);
            res.push_back(0xCD);
        } else {  // 其他字节保持不变
            res.push_back(v);
        }
    }
    
    // 计算新的长度(包括长度字节本身)
    int n_len = 1 + res.size();
    
    // 输出结果
    cout << uppercase << hex << n_len;
    for (int v : res) {
        cout << " " << uppercase << hex << v;
    }
    cout << endl;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    esc();
    return 0;
}
  • Java
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String[] hex = sc.nextLine().split("\\s+");
        
        List<Integer> vals = new ArrayList<>();
        
        // 处理输入的十六进制报文(跳过长度字节)
        for (int i = 1; i < hex.length; i++) {
            vals.add(Integer.parseInt(hex[i], 16));
        }
        
        // 进行转义处理
        List<Integer> res = new ArrayList<>();
        for (int v : vals) {
            if (v == 0x0A) {  // 转义 0x0A
                res.add(0x12);
                res.add(0x34);
            } else if (v == 0x0B) {  // 转义 0x0B
                res.add(0xAB);
                res.add(0xCD);
            } else {  // 其他字节保持不变
                res.add(v);
            }
        }
        
        // 计算新的长度(包括长度字节本身)
        int newLen = 1 + res.size();
        
        // 输出结果
        StringBuilder sb = new StringBuilder();
        sb.append(Integer.toHexString(newLen).toUpperCase());
        
        for (int v : res) {
            sb.append(" ").append(Integer.toHexString(v).toUpperCase());
        }
        
        System.out.println(sb);
    }
}

02. 古镇探秘最佳路线

问题描述

小柯计划前往一座历史悠久的古镇游玩。古镇的街道呈现网格状排列,小柯从古镇的西北角(左上角)出发,目标是到达东南角(右下角)的知名景点。

每条街道都有不同的通行费用(可能是因为有特色小店或者表演需要支付门票)。小柯想要找到一条总花费最少的路径。

小柯只能向右或向下移动,不能往回走。她需要你的帮助来规划一条最经济的路线。

输入格式

第一行包含一个正整数 ,表示古镇街道的行数。

接下来 行,每行包含若干个用空格分隔的正整数,表示每个路口的通行费用。每行的数字个数相同,假设为

输出格式

输出一个整数,表示从左上角到右下角的最小总花费。

样例输入

3
1 3 1
1 5 1
4 2 1

样例输出

7

数据范围

  • 每个路口的通行费用
样例 解释说明
样例1 古镇街道构成一个 3×3 的网格。小柯从左上角出发,经过的路径为 (1,1) -> (1,2) -> (2,2) -> (3,2) -> (3,3),总花费为 1+3+5+2+1=12。但最优路径是 (1,1) -> (2,1) -> (3,1) -> (3,2) -> (3,3),总花费为 1+1+4+1+0=7。

题解

这道题是经典的最小路径和问题,非常适合使用动态规划来解决。

首先,我们来分析一下问题:

  1. 我们需要从左上角出发,到达右下角
  2. 每次只能向右或向下移动
  3. 每个位置都有一个通行费用
  4. 我们需要找到总费用最小的路径

这个问题的状态定义很直观:设 dp[i][j] 表示从起点 (0,0) 到达位置 (i,j) 的最小总费用。

状态转移方程也很容易推导:

  • 对于第一行 (i=0):dp[0][j] = dp[0][j-1] + grid[0][j],即只能从左边来
  • 对于第一列 (j=0):dp[i][0] = dp[i-1][0] + grid[i][0],即只能从上面来
  • 对于其他位置:dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid[i][j],即可以从上面或左边来,选择较小的那个

初始条件是 dp[0][0] = grid[0][0],表示起点的费用。

算法的时间复杂度是 O(MN),空间复杂度也是 O(MN)。对于题目给出的数据范围(M, N ≤ 100),这个算法是完全可以接受的。

实际上,由于我们在计算 dp[i][j] 时只需要 dp[i-1][j] 和 dp[i][j-1],所以可以将空间复杂度优

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

互联网刷题笔试宝典 文章被收录于专栏

互联网刷题笔试宝典,这里涵盖了市面上大部分的笔试题合集,希望助大家春秋招一臂之力

全部评论

相关推荐

评论
3
1
分享

创作者周榜

更多
牛客网
牛客企业服务