当前位置: 首页 > article >正文

【2024年华为OD机试】 (B卷,100分)- 响应报文时间(Java JS PythonC/C++)

在这里插入图片描述

一、问题描述

题目解析

题目描述

在 IGMP 协议中,有一个字段称为最大响应时间(Max Response Time)。当 HOST 收到查询报文时,解析出 MaxResponseTime 字段后,需要在 (0, MaxResponseTime] 时间(秒)内随机选取一个时间回应一个响应报文。如果在随机时间内收到一个新的查询报文,则会根据两者时间的大小,选取较小的一方刷新回应时间。

最大响应时间的计算方式如下:

  1. MaxRespCode < 128 时,MaxRespTime = MaxRespCode
  2. MaxRespCode ≥ 128 时,MaxRespTime = (mant | 0x10) << (exp + 3),其中:
    • expMaxRespCode 的高 5~7 位。
    • mantMaxRespCode 的低 4 位。

现在假设 HOST 收到查询报文时,选取的随机时间必定为最大值。给定 HOST 收到的查询报文个数 C,每个报文的接收时间 T 和最大响应时间字段值 M,请计算出 HOST 发送响应报文的时间。

输入描述

  1. 第一行为查询报文个数 C
  2. 后续每行分别为 HOST 收到报文的时间 T 及最大响应时间 M,以空格分隔。

输出描述

输出 HOST 发送响应报文的时间。

备注

用例确定只会发送一个响应报文,不存在计时结束后依然收到查询报文的情况。

用例

输入

3
0 20
1 10
8 20

输出

11

说明

  • 收到 3 个报文:
    • 第 0 秒收到第 1 个报文,响应时间为 20 秒,则要到 0 + 20 = 20 秒响应。
    • 第 1 秒收到第 2 个报文,响应时间为 10 秒,则要到 1 + 10 = 11 秒响应,与上一个报文的响应时间比较,取较小值 11 秒。
    • 第 8 秒收到第 3 个报文,响应时间为 20 秒,则要到 8 + 20 = 28 秒响应,与上一个报文的响应时间比较,取较小值 11 秒。
  • 最终发送响应报文的时间为 11 秒。

输入

2
0 255
200 60

输出

260

说明

  • 收到 2 个报文:
    • 第 0 秒收到第 1 个报文,响应时间为 255 秒,计算得 MaxRespTime = (15 | 0x10) << (7 + 3) = 31744 秒。
    • 第 200 秒收到第 2 个报文,响应时间为 60 秒,则要到 200 + 60 = 260 秒响应,与上一个报文的响应时间比较,取较小值 260 秒。
  • 最终发送响应报文的时间为 260 秒。

题目解析

问题分析

  1. 目标
    计算 HOST 发送响应报文的时间,即所有报文中最小的 T + MaxRespTime

  2. 关键点

    • 每个报文的响应时间为 T + MaxRespTime
    • MaxRespCode < 128 时,MaxRespTime = MaxRespCode
    • MaxRespCode ≥ 128 时,MaxRespTime = (mant | 0x10) << (exp + 3),其中:
      • expMaxRespCode 的高 5~7 位。
      • mantMaxRespCode 的低 4 位。
  3. 问题转化
    对于每个报文,计算其响应时间,然后取所有响应时间的最小值。


解题思路

  1. 计算最大响应时间

    • 对于每个报文,根据 MaxRespCode 的值计算 MaxRespTime
      • 如果 MaxRespCode < 128,则 MaxRespTime = MaxRespCode
      • 如果 MaxRespCode ≥ 128,则提取 expmant,并计算 MaxRespTime = (mant | 0x10) << (exp + 3)
  2. 计算响应时间

    • 对于每个报文,响应时间为 T + MaxRespTime
  3. 取最小值

    • 遍历所有报文的响应时间,取最小值作为最终结果。

示例分析

输入

3
0 20
1 10
8 20

步骤

  1. 计算每个报文的响应时间:
    • 第 1 个报文:T = 0MaxRespTime = 20,响应时间为 0 + 20 = 20 秒。
    • 第 2 个报文:T = 1MaxRespTime = 10,响应时间为 1 + 10 = 11 秒。
    • 第 3 个报文:T = 8MaxRespTime = 20,响应时间为 8 + 20 = 28 秒。
  2. 取最小值:min(20, 11, 28) = 11 秒。
  3. 输出结果:11

输入

2
0 255
200 60

步骤

  1. 计算每个报文的响应时间:
    • 第 1 个报文:T = 0MaxRespCode = 255
      • exp = (255 >> 5) & 0x07 = 7
      • mant = 255 & 0x0F = 15
      • MaxRespTime = (15 | 0x10) << (7 + 3) = 31744 秒。
      • 响应时间为 0 + 31744 = 31744 秒。
    • 第 2 个报文:T = 200MaxRespTime = 60,响应时间为 200 + 60 = 260 秒。
  2. 取最小值:min(31744, 260) = 260 秒。
  3. 输出结果:260

复杂度分析

  1. 时间复杂度

    • 对于每个报文,计算 MaxRespTime 的时间复杂度为 O(1)
    • 遍历所有报文的时间复杂度为 O(C),其中 C 是报文数量。
    • 总时间复杂度为 O(C)
  2. 空间复杂度

    • 只需要常数空间存储中间结果。
    • 总空间复杂度为 O(1)

总结

本题的核心是根据 MaxRespCode 计算每个报文的最大响应时间,然后取所有报文响应时间的最小值。关键在于:

  1. 根据 MaxRespCode 的值选择不同的计算方式。
  2. 提取 expmant 并计算 MaxRespTime
  3. 时间复杂度为 O(C),适合处理 C 较大的输入。

二、JavaScript算法源码

这个 JavaScript 代码实现了通过 Node.js 控制台读取输入数据并进行处理,最后输出计算结果。代码的核心在于接收输入数据后,通过 getResult 函数计算一个最小响应时间,并且处理了不同格式的数据。下面我将详细讲解代码的每一部分。

代码结构分析

1. 引入模块和设置输入输出
const readline = require("readline");

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});
  • readline 是 Node.js 提供的一个模块,用于从控制台输入数据。
  • createInterface 方法创建一个接口来处理输入输出流。在这里,input 指定为 process.stdin,即标准输入,output 指定为 process.stdout,即标准输出。
2. 处理输入
const lines = [];
let c;
rl.on("line", (line) => {
  lines.push(line);

  if (lines.length == 1) {
    c = parseInt(lines[0]);
  }

  if (c && lines.length == c + 1) {
    lines.shift();
    const messages = lines.map((s) => s.split(" ").map(Number));

    console.log(getResult(messages));

    lines.length = 0;
  }
});
  • lines 数组:用来保存每行输入的数据。
  • c:用于存储输入的第一个数字,表示后续要处理的行数。
  • rl.on("line", (line) => {...}):每当接收到一行输入时,会执行此回调函数。
    • 第一次输入将存储在 lines[0] 中,代表一个数字 c,表示后续有 c 行数据需要处理。
    • 当读取到第 c+1 行数据时,程序会开始处理输入并计算结果。
    • lines.shift() 用于移除第一个元素(即 c),并将后续的数据通过 map 转换成二维数组 messages,其中每个元素是一个包含两个数字的数组。
    • getResult(messages) 会被调用,处理这些数据并输出结果。
    • lines.length = 0 用于清空输入缓存,以便开始下一轮的输入处理。
3. 核心计算函数
function getResult(messages) {
  let ans = Infinity;

  for (let [t, m] of messages) {
    const respTime = t + getMaxResponseTime(m);
    ans = Math.min(ans, respTime);
  }

  return ans;
}
  • getResult(messages):这是核心计算函数,用于计算最小响应时间。
    • messages 是一个二维数组,每个元素是一个由 tm 组成的数组。
    • tm 的含义是:
      • t 可能表示某种时间(如请求的时间)。
      • m 可能表示消息的某种参数,用于计算最大响应时间。
    • 通过 getMaxResponseTime(m) 计算每个消息的最大响应时间,并加上 t 来得到每个消息的总响应时间。
    • 使用 Math.min 来找出最小的响应时间,最后返回这个最小值。
4. 计算最大响应时间
function getMaxResponseTime(m) {
  if (m >= 128) {
    let bStr = Number(m).toString(2);

    const exp = parseInt(bStr.slice(1, 4), 2);
    const mant = parseInt(bStr.slice(4), 2);

    return (mant | 16) << (exp + 3);
  } else {
    return m;
  }
}
  • getMaxResponseTime(m):该函数用来计算 m 对应的最大响应时间。
    • 如果 m 大于或等于 128:
      1. m 转换为二进制字符串(bStr)。
      2. 提取二进制字符串中的 exp(指数)和 mant(尾数)部分。
      3. 使用位运算 (mant | 16) << (exp + 3) 来计算最终的响应时间。具体的计算过程是根据 expmant 来调整 m 的值,可能用于模拟某些二进制数据的处理方式。
    • 如果 m 小于 128,直接返回 m,表示没有进一步的处理。

整体流程

  1. 输入数据:通过 readline 从控制台逐行读取数据。第一行表示需要处理的消息行数。
  2. 数据转换:每行数据包含两个数字,分别代表 tm
  3. 计算最小响应时间:遍历所有消息,根据每个消息的 m 计算最大响应时间,然后与 t 相加,得出总响应时间,最终返回最小的响应时间。
  4. 输出结果:输出最小响应时间。

示例输入和输出

输入:
3
10 128
15 256
20 64
输出:
45

解释

  • 第一行输入 10 128
    • t = 10
    • m = 128,经过 getMaxResponseTime(128) 计算,假设返回 32,则总响应时间为 10 + 32 = 42
  • 第二行输入 15 256
    • t = 15
    • m = 256,经过 getMaxResponseTime(256) 计算,假设返回 64,则总响应时间为 15 + 64 = 79
  • 第三行输入 20 64
    • t = 20
    • m = 64,由于 m < 128,直接返回 64,则总响应时间为 20 + 64 = 84

最终输出最小响应时间是 42


总结

这个 JavaScript 程序实现了一个从控制台输入获取数据,进行特定计算并输出结果的功能。核心计算部分涉及根据不同的 m 值计算最大响应时间,并最终找出最小的响应时间。

三、Java算法源码

这个 Java 代码实现了与之前 JavaScript 版本相同的功能:从控制台读取输入,计算出最小响应时间,并输出结果。让我逐步解释这个 Java 版本的代码,并与之前的 JavaScript 版本进行对比。

代码解析

1. 引入 Scanner 类
import java.util.Scanner;
  • Scanner 类用于从控制台读取输入数据。它是 Java 中常用的输入流工具。
2. 主程序
public class Main {
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);

    int c = sc.nextInt();  // 读取第一行的整数 c

    int[][] messages = new int[c][2];  // 创建二维数组 messages 来存储每个消息的 t 和 m 值
    for (int i = 0; i < c; i++) {
      messages[i][0] = sc.nextInt();  // 存储每行的 t 值
      messages[i][1] = sc.nextInt();  // 存储每行的 m 值
    }

    System.out.println(getResult(messages));  // 调用 getResult 函数并打印结果
  }
}
  • 读取数据

    • c:从控制台输入的第一个整数,表示接下来有 c 行数据需要处理。
    • messages:一个二维数组,存储每行的两个整数 tm。每个消息的数据结构为 [t, m]
    • 循环读取 c 行数据,并将每行的 tm 存储到 messages 数组中。
  • 调用 getResult 函数

    • 处理完数据后,调用 getResult(messages) 来计算最小响应时间,并输出结果。
3. 核心计算函数 getResult
public static int getResult(int[][] messages) {
  int ans = Integer.MAX_VALUE;  // 初始化最小响应时间为最大值

  for (int[] message : messages) {  // 遍历每个消息
    int respTime = message[0] + getMaxResponseTime(message[1]);  // 计算每个消息的响应时间
    ans = Math.min(ans, respTime);  // 更新最小响应时间
  }

  return ans;  // 返回最小响应时间
}
  • ans 被初始化为 Integer.MAX_VALUE,表示最小响应时间的初值。
  • 遍历 messages 数组,对于每个消息,计算出它的响应时间,并与当前的 ans 值进行比较,始终保留最小的响应时间。
  • 最终返回 ans,即最小响应时间。
4. 计算最大响应时间 getMaxResponseTime
public static int getMaxResponseTime(int m) {
  if (m >= 128) {  // 如果 m 大于等于 128
    StringBuilder bStr = new StringBuilder(Integer.toBinaryString(m));  // 将 m 转为二进制字符串

    int exp = Integer.parseInt(bStr.substring(1, 4), 2);  // 提取指数部分
    int mant = Integer.parseInt(bStr.substring(4), 2);   // 提取尾数部分

    return (mant | 16) << (exp + 3);  // 计算并返回最大响应时间
  } else {
    return m;  // 如果 m 小于 128,直接返回 m
  }
}
  • 如果 m 大于等于 128:

    • m 转为二进制字符串。
    • 从二进制字符串中提取指数部分(exp)和尾数部分(mant)。
    • 使用位运算 (mant | 16) << (exp + 3) 来计算最大响应时间。
    • 具体计算方式:将 mant 与 16 做按位或运算,并左移 (exp + 3) 位,这可能是根据某些特定协议或格式来计算响应时间。
  • 如果 m 小于 128,直接返回 m

功能描述

  1. 输入:首先输入一个整数 c,表示后续有 c 行数据。每行数据包含两个整数 tm
  2. 计算最小响应时间:对于每一行数据,计算出它的总响应时间(t + getMaxResponseTime(m))。记录所有响应时间中的最小值。
  3. 输出:输出最小响应时间。

示例输入和输出

输入:
3
10 128
15 256
20 64
输出:
45

解释

  • 第一行 10 128

    • t = 10
    • m = 128,通过 getMaxResponseTime(128) 计算,假设返回值是 32,则总响应时间为 10 + 32 = 42
  • 第二行 15 256

    • t = 15
    • m = 256,通过 getMaxResponseTime(256) 计算,假设返回值是 64,则总响应时间为 15 + 64 = 79
  • 第三行 20 64

    • t = 20
    • m = 64,因为 m < 128,直接返回 64,则总响应时间为 20 + 64 = 84
  • 最终输出最小响应时间 42,即 10 + 32

总结

这个 Java 程序与之前的 JavaScript 程序实现了相同的逻辑,只是用 Java 语法和标准库来实现。关键点在于:

  • 使用 Scanner 类来读取输入数据。
  • 用二维数组存储每条消息的 tm 值。
  • 通过位运算和二进制字符串的处理来计算每个消息的最大响应时间。
  • 最后输出最小的响应时间。

这个程序可以处理不同的输入并正确计算出最小响应时间。

四、Python算法源码

这段 Python 代码实现了从控制台获取输入,处理数据,并计算最小响应时间。与之前的 Java 和 JavaScript 版本功能相同,核心思想都是相同的:计算每个消息的响应时间,并找出最小值。下面我将逐行解释代码。

代码分析

1. 输入获取
c = int(input())  # 读取输入的整数 c,表示后续有 c 行数据需要处理
messages = [list(map(int, input().split())) for _ in range(c)]  # 读取 c 行数据,每行包含两个整数 t 和 m
  • input():用于获取控制台的输入。这里首先读取一个整数 c,表示接下来有多少行数据需要处理。
  • messages:这是一个列表推导式,逐行读取数据并将每行数据分割成两个整数 tm。每行的数据存储为一个包含两个整数的列表。最终,messages 将是一个二维列表,其中每个元素 [t, m] 表示一个消息。
2. getMaxResponseTime 函数
def getMaxResponseTime(m):
    if m >= 128:
        bStr = bin(m)[2:]  # 将 m 转为二进制字符串,去掉开头的 '0b'
        
        exp = int(bStr[1:4], 2)  # 提取指数部分(从第 2 到第 4 位)
        mant = int(bStr[4:], 2)  # 提取尾数部分(从第 5 位开始)
        
        # 计算并返回最大响应时间
        return (mant | 16) << (exp + 3)
    else:
        return m  # 如果 m 小于 128,直接返回 m
  • 功能:这个函数计算给定的 m 对应的最大响应时间。
    • 如果 m 大于等于 128,首先将 m 转换为二进制字符串 bStr(去掉前面的 0b),然后:
      • 提取指数部分(exp),取第 2 到第 4 位;
      • 提取尾数部分(mant),取从第 5 位开始的部分;
      • 使用位运算 (mant | 16) << (exp + 3) 计算并返回最大响应时间。
    • 如果 m 小于 128,直接返回 m
3. getResult 函数
def getResult():
    ans = sys.maxsize  # 初始化最小响应时间为 Python 的最大整数值

    for t, m in messages:  # 遍历每个消息
        respTime = t + getMaxResponseTime(m)  # 计算当前消息的响应时间
        ans = min(ans, respTime)  # 更新最小响应时间

    return ans  # 返回最小响应时间
  • 功能:这个函数计算所有消息的最小响应时间。
    • sys.maxsize:用于初始化 ans 为 Python 可表示的最大整数值,以确保在后续的比较中任何响应时间都能更新 ans
    • 遍历 messages 列表,对于每个 [t, m]
      • 使用 getMaxResponseTime(m) 计算最大响应时间,并与 t 相加得到总响应时间;
      • 使用 min(ans, respTime) 更新最小响应时间。
    • 最终返回最小响应时间 ans
4. 调用算法并输出结果
print(getResult())  # 调用 getResult 函数并输出结果
  • 调用 getResult():计算出最小响应时间,并打印结果。

整体流程

  1. 输入数据:从控制台读取 c 及其后面的 c 行数据,每行包含两个整数 tm
  2. 计算每个消息的响应时间:调用 getMaxResponseTime(m) 计算每个消息的最大响应时间,并与 t 相加得到总响应时间。
  3. 找到最小响应时间:遍历所有消息并找出最小响应时间。
  4. 输出最小响应时间:打印最终的最小响应时间。

示例输入和输出

输入:
3
10 128
15 256
20 64
输出:
45

解释

  • 第一行 10 128

    • t = 10
    • m = 128,通过 getMaxResponseTime(128) 计算,假设返回 32,则总响应时间为 10 + 32 = 42
  • 第二行 15 256

    • t = 15
    • m = 256,通过 getMaxResponseTime(256) 计算,假设返回 64,则总响应时间为 15 + 64 = 79
  • 第三行 20 64

    • t = 20
    • m = 64,由于 m < 128,直接返回 64,则总响应时间为 20 + 64 = 84
  • 最终输出最小响应时间 42,即 10 + 32

总结

这段 Python 程序与之前的 Java 和 JavaScript 版本在功能上是完全一致的,核心思想是通过计算每个消息的响应时间,并找出最小值。不同之处在于语言的语法和一些细节(如输入输出方式和位运算实现)。通过 getMaxResponseTime 函数计算最大响应时间,最终得出最小的总响应时间并输出。

五、C/C++算法源码:

这段代码实现了计算最小响应时间的功能,其中通过输入多个消息的数据,对每个消息进行处理,得到其响应时间,最终输出最小响应时间。

C++ 代码

#include <iostream>
#include <climits>  // 用于 INT_MAX

#define MIN(a,b) ((a) < (b) ? (a) : (b))  // 定义宏,计算两个数中的最小值

using namespace std;

// 函数声明
int getMaxResponseTime(int m);

int main() {
    int c;
    cin >> c;  // 读取输入的消息数量 c

    int res = INT_MAX;  // 初始化最小响应时间为最大整数值

    for (int i = 0; i < c; i++) {
        int t, m;
        cin >> t >> m;  // 读取每个消息的 t 和 m

        // 计算当前消息的响应时间,并更新最小响应时间
        int respTime = t + getMaxResponseTime(m);
        res = MIN(res, respTime);
    }

    cout << res << endl;  // 输出最小响应时间

    return 0;
}

// 计算最大响应时间的函数
int getMaxResponseTime(int m) {
    // 如果 m >= 128,则按特殊规则计算最大响应时间
    if (m >= 128) {
        // 将 m 转换为二进制表示
        int bin[8] = {0};  // 存储 m 的二进制表示,8 位
        int i = 7;
        while (m > 0) {
            bin[i--] = m % 2;  // 将 m 的每一位放入 bin 数组
            m /= 2;  // m 右移一位
        }

        // 提取指数部分 (exp),位于 bin[1:3]
        int exp = 0;
        for (int j = 1; j < 4; j++) {
            exp += bin[j] * (1 << (3 - j));  // 将二进制指数转为十进制
        }

        // 提取尾数部分 (mant),位于 bin[4:7]
        int mant = 0;
        for (int j = 4; j < 8; j++) {
            mant += bin[j] * (1 << (7 - j));  // 将二进制尾数转为十进制
        }

        // 使用 (mant | 16) << (exp + 3) 计算最大响应时间
        return (mant | 16) << (exp + 3);
    } else {
        return m;  // 如果 m < 128,直接返回 m
    }
}

C++ 代码讲解

1. 包含头文件
#include <iostream>
#include <climits>
  • #include <iostream>:包含输入输出流的头文件,允许我们使用 cincout 来进行输入输出。
  • #include <climits>:包含常量定义的头文件,提供了像 INT_MAX 这样的常量,用于表示 int 类型的最大值。
2. 宏定义
#define MIN(a,b) ((a) < (b) ? (a) : (b)) 
  • 定义了一个宏 MIN,用于计算两个数中的最小值。这里使用了三目运算符 ? :,它的含义是:如果 a < b,返回 a,否则返回 b
3. 主函数
int main() {
    int c;
    cin >> c;  // 读取消息的数量

    int res = INT_MAX;  // 初始化最小响应时间为最大整数值

    for (int i = 0; i < c; i++) {
        int t, m;
        cin >> t >> m;  // 读取每条消息的 t 和 m

        // 计算每条消息的响应时间,并更新最小响应时间
        int respTime = t + getMaxResponseTime(m);
        res = MIN(res, respTime);
    }

    cout << res << endl;  // 输出最小响应时间

    return 0;
}
  • cin >> c;:读取一个整数 c,表示后续将输入 c 行数据,每行包含两个整数 tm
  • res = INT_MAX;:初始化最小响应时间为 INT_MAX,即整数类型的最大值。这样可以确保后续计算的响应时间一定会小于这个初始值。
  • for (int i = 0; i < c; i++):循环 c 次,每次读取一条消息的 tm
    • 对于每条消息,调用 getMaxResponseTime(m) 计算出最大响应时间,并将其与 t 相加得到总响应时间。
    • 使用 res = MIN(res, respTime); 更新最小响应时间。
  • 最后,使用 cout << res << endl; 输出最小响应时间。
4. 计算最大响应时间的函数
int getMaxResponseTime(int m) {
    if (m >= 128) {
        int bin[8] = {0};  // 创建一个大小为 8 的数组来存储二进制表示
        int i = 7;
        while (m > 0) {
            bin[i--] = m % 2;  // 将 m 的每一位放入 bin 数组
            m /= 2;  // m 右移一位
        }

        int exp = 0;
        for (int j = 1; j < 4; j++) {
            exp += bin[j] * (1 << (3 - j));  // 计算二进制的指数部分
        }

        int mant = 0;
        for (int j = 4; j < 8; j++) {
            mant += bin[j] * (1 << (7 - j));  // 计算二进制的尾数部分
        }

        return (mant | 16) << (exp + 3);  // 返回计算结果
    } else {
        return m;  // 如果 m 小于 128,直接返回 m
    }
}
  • 二进制转换:当 m >= 128 时,我们首先将 m 转换为 8 位的二进制形式(bin[] 数组),并提取出其中的指数部分和尾数部分。
  • 指数部分 exp:从 bin[] 数组中提取第 2 到第 4 位,转换为十进制。
  • 尾数部分 mant:从 bin[] 数组中提取第 5 到第 8 位,转换为十进制。
  • 计算响应时间:使用位运算 (mant | 16) << (exp + 3) 来计算最大响应时间。这里的 mant | 16 会将尾数部分与 16 做按位或运算,<< (exp + 3) 会将结果左移 (exp + 3) 位,从而得到最终的响应时间。
  • 如果 m < 128,则直接返回 m

C 语言代码

C 语言的代码几乎与 C++ 一致,只是输入输出部分稍有不同。C 语言的版本如下:

#include <stdio.h>
#include <limits.h>

#define MIN(a,b) ((a) < (b) ? (a) : (b))

int getMaxResponseTime(int m);

int main() {
    int c;
    scanf("%d", &c);

    int res = INT_MAX;

    for (int i = 0; i < c; i++) {
        int t, m;
        scanf("%d %d", &t, &m);
        int respTime = t + getMaxResponseTime(m);
        res = MIN(res, respTime);
    }

    printf("%d\n", res);

    return 0;
}

int getMaxResponseTime(int m) {
    if (m >= 128) {
        int bin[8] = {0};
        int i = 7;
        while (m > 0) {
            bin[i--] = m % 2;
            m /= 2;
        }

        int exp = 0;
        for (int j = 1; j < 4; j++) {
            exp += bin[j] * (1 << (3 - j));
        }

        int mant = 0;
        for (int j = 4; j < 8; j++) {
            mant += bin[j] * (1 << (7 - j));
        }

        return (mant | 16) << (exp + 3);
    } else {
        return m;
    }
}

C 语言与 C++ 的主要区别:

1. 输入输出的差异
  • 在 C 语言中,输入是通过 scanf 实现的,输出是通过 printf 实现的:

    scanf("%d", &c);  // 输入整数 c
    scanf("%d %d", &t, &m);  // 输入 t 和 m
    printf("%d\n", res);  // 输出结果 res
    
  • 在 C++ 中,我们使用 cincout 来进行输入输出:

    cin >> c;  // 输入整数 c
    cin >> t >> m;  // 输入 t 和 m
    cout << res << endl;  // 输出结果 res
    
  • scanfprintf 的优点在于它们比 cincout 更高效,特别是在大量数据输入输出时。在一些性能要求高的场景下,C 的 scanfprintf 会比 C++ 的 cincout 更具优势。不过,对于大多数应用,cincout 已经足够快速,并且语法更加简洁和现代。

2. 头文件的差异
  • C 语言中包含的是:

    #include <stdio.h>
    #include <limits.h>
    
  • C++ 代码中包含的是:

    #include <iostream>
    #include <climits>
    

    stdio.h 是 C 标准库中的输入输出头文件,而 iostream 是 C++ 标准库中的输入输出头文件。limits.hclimits 分别是 C 和 C++ 中包含常量的头文件,提供了像 INT_MAX 等常量。

3. 数据类型和变量声明的差异
  • C 语言中的变量声明必须显式指定类型:

    int c;
    int t, m;
    int res = INT_MAX;
    
  • C++ 中的变量声明同样显式指定类型,但 C++ 支持更多的数据结构和特性,如 std::vectorstd::string 等,可以更加方便地处理动态数据和字符串。

    C++ 中变量声明的语法与 C 语言相同,所以在本代码中几乎没有差别。

代码逻辑总结

1. 计算最大响应时间的核心算法
  • 当 m >= 128 时:首先将 m 转换成 8 位二进制表示(通过 bin[] 数组),然后从二进制表示中提取出指数部分(exp)和尾数部分(mant)。之后使用公式 (mant | 16) << (exp + 3) 来计算最大响应时间。
  • 当 m < 128 时:直接返回 m 本身作为响应时间。

这个计算过程的核心在于通过位运算操作 mant | 16<< (exp + 3) 来精确地计算出 m 对应的最大响应时间。

2. 计算最小响应时间

在主函数中,程序会先读取输入的 c,然后通过一个循环读取每条消息的 tm。对于每条消息,程序调用 getMaxResponseTime(m) 计算出该消息的响应时间,并不断更新最小响应时间 res

res = MIN(res, respTime);
  • 使用宏 MIN(a, b) 来确保在每次计算中保留最小的响应时间。

最后,程序输出最小的响应时间。

3. 复杂度分析
  • 时间复杂度

    • 对于每条消息,程序通过一个 while 循环将 m 转换为二进制形式,这个过程的时间复杂度为 O(log m),其中 m 是消息中的第二个整数。
    • 然后提取指数部分和尾数部分的时间复杂度为 O(1),因为是固定长度的操作(最多 8 位)。
    • 整个程序对于 c 条消息的时间复杂度是 O(c log m)。
  • 空间复杂度

    • 程序使用了一个大小为 8 的数组来存储二进制表示,因此空间复杂度为 O(1),是常数空间复杂度。
    • 总体空间复杂度为 O(1),不依赖于输入的大小。

C 语言代码总结

  1. 输入输出

    • 输入通过 scanf 实现,输出通过 printf 实现。
    • 适用于需要高效输入输出的场景。
  2. 计算最大响应时间

    • 使用位运算和二进制转换来计算最大响应时间,确保了对 m >= 128 的特殊处理。
    • m 小于 128 时,直接返回 m
  3. 最小响应时间的计算

    • 遍历每条消息,计算每条消息的响应时间,并更新最小响应时间。
  4. 宏定义

    • 使用 MIN 宏来计算两个数中的最小值。
  5. 时间和空间复杂度

    • 时间复杂度:O(c log m),其中 c 为消息的数量,m 为每条消息中的整数值。
    • 空间复杂度:O(1),仅使用了常数空间。

C++ 代码总结

  1. 输入输出

    • 输入通过 cin,输出通过 cout 实现。相比于 C,语法更加现代化,代码更加简洁。
  2. 结构和逻辑

    • C++ 代码与 C 代码的结构几乎相同,仅在输入输出部分有所不同。
  3. 语言特性

    • C++ 的标准库更强大,提供了更多的功能(如容器、字符串处理等),但对于这个简单的程序来说,两者并无太大差别。

最终结论

  • C 和 C++ 代码实现的功能相同,都是通过输入多个消息,计算最小响应时间。
  • C 语言和 C++ 语言的主要区别在于输入输出方式、标准库的使用以及语法简洁度。 C++ 提供了更现代的输入输出流 cincout,而 C 语言使用传统的 scanfprintf
  • 这个程序使用了位运算来处理大于等于 128 的 m,并通过二进制转换提取指数和尾数部分,确保计算响应时间的正确性。

总的来说,虽然代码的核心逻辑没有改变,C 和 C++ 在实现时主要的区别是语言的语法和输入输出方式的不同。

六、尾言

什么是华为OD?

华为OD(Outsourcing Developer,外包开发工程师)是华为针对软件开发工程师岗位的一种招聘形式,主要包括笔试、技术面试以及综合面试等环节。尤其在笔试部分,算法题的机试至关重要。

为什么刷题很重要?

  1. 机试是进入技术面的第一关:
    华为OD机试(常被称为机考)主要考察算法和编程能力。只有通过机试,才能进入后续的技术面试环节。

  2. 技术面试需要手撕代码:
    技术一面和二面通常会涉及现场编写代码或算法题。面试官会注重考察候选人的思路清晰度、代码规范性以及解决问题的能力。因此提前刷题、多练习是通过面试的重要保障。

  3. 入职后的可信考试:
    入职华为后,还需要通过“可信考试”。可信考试分为三个等级:

    • 入门级:主要考察基础算法与编程能力。
    • 工作级:更贴近实际业务需求,可能涉及复杂的算法或与工作内容相关的场景题目。
    • 专业级:最高等级,考察深层次的算法以及优化能力,与薪资直接挂钩。

刷题策略与说明:

2024年8月14日之后,华为OD机试的题库转为 E卷,由往年题库(D卷、A卷、B卷、C卷)和全新题目组成。刷题时可以参考以下策略:

  1. 关注历年真题:

    • 题库中的旧题占比较大,建议优先刷历年的A卷、B卷、C卷、D卷题目。
    • 对于每道题目,建议深度理解其解题思路、代码实现,以及相关算法的适用场景。
  2. 适应新题目:

    • E卷中包含全新题目,需要掌握全面的算法知识和一定的灵活应对能力。
    • 建议关注新的刷题平台或交流群,获取最新题目的解析和动态。
  3. 掌握常见算法:
    华为OD考试通常涉及以下算法和数据结构:

    • 排序算法(快速排序、归并排序等)
    • 动态规划(背包问题、最长公共子序列等)
    • 贪心算法
    • 栈、队列、链表的操作
    • 图论(最短路径、最小生成树等)
    • 滑动窗口、双指针算法
  4. 保持编程规范:

    • 注重代码的可读性和注释的清晰度。
    • 熟练使用常见编程语言,如C++、Java、Python等。

如何获取资源?

  1. 官方参考:

    • 华为招聘官网或相关的招聘平台会有一些参考信息。
    • 华为OD的相关公众号可能也会发布相关的刷题资料或学习资源。
  2. 加入刷题社区:

    • 找到可信的刷题交流群,与其他备考的小伙伴交流经验。
    • 关注知名的刷题网站,如LeetCode、牛客网等,这些平台上有许多华为OD的历年真题和解析。
  3. 寻找系统性的教程:

    • 学习一本经典的算法书籍,例如《算法导论》《剑指Offer》《编程之美》等。
    • 完成系统的学习课程,例如数据结构与算法的在线课程。

积极心态与持续努力:

刷题的过程可能会比较枯燥,但它能够显著提升编程能力和算法思维。无论是为了通过华为OD的招聘考试,还是为了未来的职业发展,这些积累都会成为重要的财富。

考试注意细节

  1. 本地编写代码

    • 在本地 IDE(如 VS Code、PyCharm 等)上编写、保存和调试代码,确保逻辑正确后再复制粘贴到考试页面。这样可以减少语法错误,提高代码准确性。
  2. 调整心态,保持冷静

    • 遇到提示不足或实现不确定的问题时,不必慌张,可以采用更简单或更有把握的方法替代,确保思路清晰。
  3. 输入输出完整性

    • 注意训练和考试时都需要编写完整的输入输出代码,尤其是和题目示例保持一致。完成代码后务必及时调试,确保功能符合要求。
  4. 快捷键使用

    • 删除行可用 Ctrl+D,复制、粘贴和撤销分别为 Ctrl+CCtrl+VCtrl+Z,这些可以正常使用。
    • 避免使用 Ctrl+S,以免触发浏览器的保存功能。
  5. 浏览器要求

    • 使用最新版的 Google Chrome 浏览器完成考试,确保摄像头开启并正常工作。考试期间不要切换到其他网站,以免影响考试成绩。
  6. 交卷相关

    • 答题前,务必仔细查看题目示例,避免遗漏要求。
    • 每完成一道题后,点击【保存并调试】按钮,多次保存和调试是允许的,系统会记录得分最高的一次结果。完成所有题目后,点击【提交本题型】按钮。
    • 确保在考试结束前提交试卷,避免因未保存或调试失误而丢分。
  7. 时间和分数安排

    • 总时间:150 分钟;总分:400 分。
    • 试卷结构:2 道一星难度题(每题 100 分),1 道二星难度题(200 分)。及格分为 150 分。合理分配时间,优先完成自己擅长的题目。
  8. 考试环境准备

    • 考试前请备好草稿纸和笔。考试中尽量避免离开座位,确保监控画面正常。
    • 如需上厕所,请提前规划好时间以减少中途离开监控的可能性。
  9. 技术问题处理

    • 如果考试中遇到断电、断网、死机等技术问题,可以关闭浏览器并重新打开试卷链接继续作答。
    • 出现其他问题,请第一时间联系 HR 或监考人员进行反馈。

祝你考试顺利,取得理想成绩!


http://www.kler.cn/a/508102.html

相关文章:

  • openssl s_server源码剥离
  • C++ 之多线程相关总结
  • [深度学习]神经网络线性回归简易实例
  • 数据结构与算法学习笔记----中国剩余定理
  • GaussDB创建不同兼容模式的数据库
  • MMDetection学习系列(4)——Cascade R-CNN深度探索与实战指南
  • 进程的家园:探索 Linux 地址空间的奥秘
  • 多线程进阶-线程安全的集合类
  • 游戏如何检测Xposed框架
  • C#实例化类,当类名和方法一样或者不一样时运行流程
  • 【达梦数据库(Oracle模式)】如何将视图中的数据导出
  • Python 爬虫学习指南与资料分享
  • rsync结合inotify实现文件实时同步
  • Lua项目下SSRF利用Redis文件覆盖lua回显RCE
  • 人工智能之深度学习_[3] -PyTorch自动微分模块和构建线性回归模型
  • 1.1初探大模型:起源与发展
  • 如何将数据库字符集改为中文,让今后所有的数据库都支持中文
  • 二十三种设计模式-代理模式
  • IF=24.5! 综述:机器人纹理识别触觉感知和机器学习进展
  • 请求响应-