华为OD机试 - 报文响应时间 - 贪心算法、位运算(Python/JS/C/C++ 2024 E卷 200分)

在这里插入图片描述

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

专栏导读

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

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

一、题目描述

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

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

  • 当 Max Resp Code < 128, Max Resp Time = Max Resp Code;
  • 当 Max Resp Code ≥ 128, Max Resp Time = (mant | 0x10) << (exp + 3);

在这里插入图片描述

注:

exp 最大响应时间的高5~7位: mant 为最大响应时间的低4位。

其中接收到的 MaxRespCode 最大值为 255, 以上出现所有字段均为无符号数。

现在我们认为 HOST 收到查询报文时, 选取的随机时间必定为最大值, 现给出 HOST 收到查询报文个数 C, HOST 收到该报文的时间 T, 以及查询报文的最大响应时间字段值 M, 请计算出 HOST 发送响应报文的时间。

二、输入描述

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

三、输出描述

HOST 发送响应报文的时间。

备注

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

四、测试用例

测试用例1:

1、输入

3
0 20
1 10
8 20

2、输出

11

3、说明

收到3个报文,

  • 第0秒收到第1个报文,响应时间为20秒,则要到0+20=20秒响应;
  • 第1秒收到第2个报文,响应时间为10秒,则要到1+10=11秒响应,与上面的报文的响应时间比较获得响应时间最小为11秒;
  • 第8秒收到第3个报文,响应时间为20秒,则要到8+20=28秒响应,与第上面的报文的响应时间比较获得响应时间最小为11秒;

最终得到最小响应报文时间为11秒

测试用例2:

1、输入

2
0 255
200 60

2、输出

260

3、说明

收到2个报文,

  • 第0秒收到第1个报文,响应时间为255秒,则要到(15 | 0x10) << (7 + 3)=31744秒响应;(mant = 15,exp = 7)
  • 第200秒收到第2个报文,响应时间为60秒,则要到200+60=260秒响应,与第上面的报文的响应时间比较获得响应时间最小为260秒;

最终得到最小响应报文时间为260秒

五、解题思路

1、贪心算法

贪心算法(Greedy Algorithm)是一种在每一步选择中都采取当前最优解的算法。它的思想是每一步都做出一个局部最优的选择,以期望通过局部最优解推导出全局最优解。贪心算法通常用于优化问题中,它不回溯,即不会重新考虑之前做出的选择,因此效率较高。

贪心算法的典型特点是:总是选择在当前情况下最优的解,而不考虑全局最优解的可能性。这个策略在有些问题中可以得到全局最优解,但在其他问题中则只能得到近似解。

2、贪心算法适用哪些场景?

贪心算法适用于那些具有贪心选择性质和最优子结构性质的问题。

贪心选择性质:每次的局部最优选择,最终可以得到问题的全局最优解。

最优子结构性质:问题的最优解包含了其子问题的最优解,也就是通过解决子问题可以得到全局最优解。

以下是一些经典的贪心算法适用场景:

  1. 最小生成树问题(Minimum Spanning Tree):
    • 如 Prim 算法、Kruskal 算法等,它们通过贪心策略选取当前权重最小的边来构建最小生成树。
  2. 单源最短路径问题:
    • Dijkstra 算法是典型的贪心算法应用,它在每一步选取距离当前源节点最近的节点进行处理,逐步找出最短路径。
  3. 活动选择问题:
    • 给定一系列需要在特定时间内进行的活动,活动之间可能会冲突。贪心算法选择开始时间最早且结束时间最短的活动,使得能够安排最多的活动。
  4. 背包问题(贪心解法):
    • 背包问题中,贪心算法通过选择单位价值最高的物品,试图最大化背包能装下的总价值(这是近似解,而非最优解,适用于"分数背包问题")。
  5. 霍夫曼编码:
    • 霍夫曼编码用于数据压缩。它通过贪心策略构建一个最优的二叉树,使得字符的编码长度最短。
  6. 区间调度问题:
    • 当你有一系列的任务或活动,每个活动有开始时间和结束时间,目的是在不重叠的情况下安排尽可能多的活动。通过选择最早结束的活动,贪心策略可以找到最优解。

3、为什么采用贪心算法?

每当 HOST 收到一个新的查询报文时,需要重新计算它的响应时间,且会选择在所有报文中最小的响应时间作为最终的响应时间。

题目要求在每次收到新的查询报文时,根据已有报文的响应时间和当前报文的最大响应时间,做出局部最优选择——即选择两者中较小的响应时间来更新最终响应时间。这正是贪心算法的核心思想:每一步都选择当前的最优解(最小响应时间),逐步逼近全局最优解。

在这个问题中,我们始终可以通过对比每个报文的响应时间,选择最小的那个作为当前的最优解,这样不断更新,直到处理完所有报文,最终得到全局最优的响应时间。

4、详细步骤

  1. 读取输入:首先读取输入的查询报文个数 C 以及每条报文的时间 T 和最大响应时间字段 M。
  2. 计算最大响应时间:根据题目的描述,如果 MaxRespCode 小于 128,直接取它作为最大响应时间。如果 MaxRespCode 大于等于 128,需要计算 mant | 0x10 << (exp + 3) 的值,其中 mant 是 MaxRespCode 的低 4 位,exp 是其高 5~7 位。
  3. 计算每条报文的实际响应时间:对于每条报文,计算它的最大响应时间,并结合 HOST 收到该报文的时间,计算出此报文的响应时间。
  4. 比较响应时间:对于多条报文的响应时间,选择最小的时间作为 HOST 的最终响应时间。
  5. 输出结果:输出最小的响应时间。

5、算法的时间复杂度

该算法的时间复杂度是 O©,其中 C 是查询报文的个数。因为我们需要遍历所有的报文,每条报文只需常数时间(O(1))计算其最大响应时间和更新最小响应时间。

6、算法的空间复杂度

由于使用的主要数据结构是基本数据类型,没有使用复杂的数据结构,且存储量与报文个数无关,因此空间复杂度为 O(1)。

六、Python算法源码

def calculate_max_response_time(max_resp_code):
    """
    计算 Max Response Time
    :param max_resp_code: 最大响应时间字段 M
    :return: 计算后的最大响应时间
    """
    if max_resp_code < 128:
        # 如果 MaxRespCode 小于 128,直接返回 MaxRespCode
        return max_resp_code
    else:
        # 如果 MaxRespCode ≥ 128,计算公式:(mant | 0x10) << (exp + 3)
        mant = max_resp_code & 0x0F  # 取低4位
        exp = (max_resp_code >> 4) & 0x07  # 取高5~7位
        return (mant | 0x10) << (exp + 3)  # 根据公式计算


def main():
    # 创建 input 读取输入
    C = int(input())  # 读取查询报文个数 C

    # 初始化最小响应时间为一个大数
    min_response_time = float('inf')

    # 处理每一个报文
    for i in range(C):
        # 读取 HOST 收到报文的时间 T 和最大响应时间字段 M
        T, M = map(int, input().split())

        # 计算最大响应时间
        max_response_time = calculate_max_response_time(M)

        # 计算该报文的最终响应时间 = 收到时间 T + 最大响应时间
        response_time = T + max_response_time

        # 更新最小响应时间
        min_response_time = min(min_response_time, response_time)

    # 输出最小的响应时间
    print(min_response_time)


if __name__ == "__main__":
    main()

七、JavaScript算法源码

function calculateMaxResponseTime(maxRespCode) {
    /**
     * 计算 Max Response Time
     * @param maxRespCode: 最大响应时间字段 M
     * @return: 计算后的最大响应时间
     */
    if (maxRespCode < 128) {
        // 如果 MaxRespCode 小于 128,直接返回 MaxRespCode
        return maxRespCode;
    } else {
        // 如果 MaxRespCode ≥ 128,计算公式:(mant | 0x10) << (exp + 3)
        let mant = maxRespCode & 0x0F;  // 取低4位
        let exp = (maxRespCode >> 4) & 0x07;  // 取高5~7位
        return (mant | 0x10) << (exp + 3);  // 根据公式计算
    }
}

function main() {
    // 读取输入(假设使用Node.js的标准输入)
    const readline = require('readline');
    const rl = readline.createInterface({
        input: process.stdin,
        output: process.stdout
    });

    let inputLines = [];
    let lineNumber = 0;

    rl.on('line', (line) => {
        inputLines.push(line);
        lineNumber++;

        if (lineNumber > inputLines[0]) {
            rl.close();  // 当读取的行数达到输入的报文数量时,结束输入
        }
    });

    rl.on('close', () => {
        let C = parseInt(inputLines[0]);  // 读取查询报文个数 C
        let minResponseTime = Number.MAX_SAFE_INTEGER;  // 初始化最小响应时间为一个大数

        // 处理每一个报文
        for (let i = 1; i <= C; i++) {
            let [T, M] = inputLines[i].split(' ').map(Number);  // 读取 HOST 收到报文的时间 T 和最大响应时间字段 M

            // 计算最大响应时间
            let maxResponseTime = calculateMaxResponseTime(M);

            // 计算该报文的最终响应时间 = 收到时间 T + 最大响应时间
            let responseTime = T + maxResponseTime;

            // 更新最小响应时间
            minResponseTime = Math.min(minResponseTime, responseTime);
        }

        // 输出最小的响应时间
        console.log(minResponseTime);
    });
}

// 调用主函数
main();

八、C算法源码

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

// 计算 Max Response Time
int calculateMaxResponseTime(int maxRespCode) {
    if (maxRespCode < 128) {
        // 如果 MaxRespCode 小于 128,直接返回 MaxRespCode
        return maxRespCode;
    } else {
        // 如果 MaxRespCode ≥ 128,计算公式:(mant | 0x10) << (exp + 3)
        int mant = maxRespCode & 0x0F; // 取低4位
        int exp = (maxRespCode >> 4) & 0x07; // 取高5~7位
        return (mant | 0x10) << (exp + 3); // 根据公式计算
    }
}

int main() {
    int C; // 查询报文个数
    scanf("%d", &C);

    int minResponseTime = INT_MAX; // 初始化最小响应时间为一个大数

    // 处理每一个报文
    for (int i = 0; i < C; i++) {
        int T, M;
        // 读取 HOST 收到报文的时间 T 和最大响应时间字段 M
        scanf("%d %d", &T, &M);

        // 计算最大响应时间
        int maxResponseTime = calculateMaxResponseTime(M);

        // 计算该报文的最终响应时间 = 收到时间 T + 最大响应时间
        int responseTime = T + maxResponseTime;

        // 更新最小响应时间
        if (responseTime < minResponseTime) {
            minResponseTime = responseTime;
        }
    }

    // 输出最小的响应时间
    printf("%d\n", minResponseTime);

    return 0;
}

九、C++算法源码

#include <iostream>
#include <climits> // 用于 INT_MAX
using namespace std;

// 计算 Max Response Time
int calculateMaxResponseTime(int maxRespCode) {
    if (maxRespCode < 128) {
        // 如果 MaxRespCode 小于 128,直接返回 MaxRespCode
        return maxRespCode;
    } else {
        // 如果 MaxRespCode ≥ 128,计算公式:(mant | 0x10) << (exp + 3)
        int mant = maxRespCode & 0x0F; // 取低4位
        int exp = (maxRespCode >> 4) & 0x07; // 取高5~7位
        return (mant | 0x10) << (exp + 3); // 根据公式计算
    }
}

int main() {
    int C; // 查询报文个数
    cin >> C;

    int minResponseTime = INT_MAX; // 初始化最小响应时间为一个大数

    // 处理每一个报文
    for (int i = 0; i < C; i++) {
        int T, M;
        // 读取 HOST 收到报文的时间 T 和最大响应时间字段 M
        cin >> T >> M;

        // 计算最大响应时间
        int maxResponseTime = calculateMaxResponseTime(M);

        // 计算该报文的最终响应时间 = 收到时间 T + 最大响应时间
        int responseTime = T + maxResponseTime;

        // 更新最小响应时间
        minResponseTime = min(minResponseTime, responseTime);
    }

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

    return 0;
}


🏆下一篇:华为OD机试真题 - 简易内存池(Python/JS/C/C++ 2024 E卷 200分)

🏆本文收录于,华为OD机试真题(Python/JS/C/C++)

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

在这里插入图片描述

  • 5
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

哪 吒

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

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

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

打赏作者

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

抵扣说明:

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

余额充值