华为OD机试 - 吃到最多的刚好合适的菜(Java & JS & Python & C & C++)

文章讲述了在一个有限手速的情况下,如何合理安排捞取时间,以在火锅中最多吃到达到合适状态的菜品。给出了Java、JavaScript、Python和C/C++的算法实现,展示了如何利用排序和遍历解决这个问题。
摘要由CSDN通过智能技术生成

一、题目描述

入职后,导师会请你吃饭,你选择了火锅。

火锅里会在不同时间下很多菜。

不同食材要煮不同的时间,才能变得刚好合适。你希望吃到最多的刚好合适的菜,但你的手速不够快,用m代表手速,每次下手捞菜后至少要过m庙才能在捞(每次只能捞一个)。

那么用最合理的策略,最多能吃到多少刚好合适的菜?

二、输入描述

第一行两个整数n,m,其中n代表往锅里下的菜的个数,m代表手速。

接下来有n行,每行有两个数x,y代表第x秒下的菜过y秒才能变得刚好合适。

(1 < n, m < 1000)

(1 < x, y < 1000)

三、输出描述

输出一个整数代表用最合理的策略,最多能吃到刚好合适的菜的数量。

四、解题思路

题目要求用最合理的策略,最多能吃到刚好合适的菜的数量。每道菜下锅后需要经过一定的时间才能变得刚好合适,而你的手速为 m,每次捞菜后至少需要过 m 秒才能再次捞菜。

  1. 读取输入的菜的数量 n 和手速 m;
  2. 创建两个长度为 n 的数组 arr1 和 arr2,分别用于存储每道菜的下锅时间和变得刚好合适所需的时间;
  3. 使用循环读取每道菜的下锅时间和变得刚好合适所需的时间,将其存入数组 arr1 和 arr2 中;
  4. 创建一个长度为 n 的数组 arrTime,用于存储每道菜可以吃到的时间;
  5. 遍历数组 arr1 和 arr2,将每道菜的下锅时间和变得刚好合适所需的时间相加,存入数组 arrTime 中;
  6. 对数组 arrTime 进行从小到大的排序,以便后续比较计算;
  7. 创建一个长度为 n 的数组 arrCount,用于记录每道菜是否可以吃到。初始时,将第一道菜的标记设置为 1;
  8. 使用变量 next 记录当前可以吃到的菜的索引,初始值为 0;
  9. 从第二道菜开始遍历数组 arrTime;
  10. 如果当前菜的时间大于等于 (前一道菜的时间 + m),表示可以吃到这道菜,将 arrCount 对应位置的标记设置为 1,并更新 next 的值为当前菜的索引;
  11. 使用变量 count 记录可以吃到的菜的数量,初始值为 0;
  12. 遍历数组 arrCount,如果某道菜的标记大于 0,表示可以吃到,将 count 自增;
  13. 输出 count,表示最多能吃到刚好合适的菜的数量。

五、Java算法源码

public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    while (sc.hasNextInt()) {
        int n = sc.nextInt();
        int m = sc.nextInt();
        int[] arr1 = new int[n];
        int[] arr2 = new int[n];
        for (int i = 0; i < n; i++) {
            arr1[i] = sc.nextInt();
            arr2[i] = sc.nextInt();
        }
        // 设置一个数组,存放每道菜可以吃到的时间。
        int[] arrTime = new int[n];
        for (int i = 0; i < n; i++) {
            arrTime[i] = arr1[i] + arr2[i];
        }
        // 对数组进行从小到大进行排序,这样便于后面比较计算
        Arrays.sort(arrTime);

        // 新建一个数组,和数组arrTime对应,用于记录每道菜是否可以吃到,可以吃到标记加1.
        int[] arrCount = new int[n];

        int next = 0;
        arrCount[0] = 1;
        for (int i = 1; i < n; i++) {
            if (arrTime[i] >= (arrTime[next] + m)) {
                arrCount[i] = 1;
                next = i;
            }
        }

        int count = 0;
        for (int i = 0; i < n; i++) {
            if (arrCount[i] > 0) {
                count++;
            }
        }
        System.out.println(count);
    }
}

六、效果展示

1、输入

2 1
1 2
2 1

2、输出

1

3、思路

一共下了两个菜,在第一秒下的菜需要到第三秒才能吃,在第二秒下的菜,也要第三秒才能吃,所以只能吃一个。

4、解题思路

  1. 菜可以吃的秒数=下菜的秒数x+菜适合吃的秒数y
  2. 第一个菜可以直接吃,后面的菜必须在吃的秒数上加上手速
  3. 同一秒的菜肯定只能吃一个

七、JavaScript算法源码

// 读取输入流,这里使用Node.js的readline模块  
const readline = require('readline');  
const rl = readline.createInterface({  
    input: process.stdin,  
    output: process.stdout  
});  
  
// 主函数,读取输入并处理  
async function main() {  
    let input;  
    while ((input = await rl.question('请输入两道菜的制作时间(每道两个整数,用空格分隔,多组输入以EOF结束): ')) {  
        // 将输入按空格分割成数组  
        const parts = input.split(' ').map(Number);  
        // 确保有正确的输入数量  
        if (parts.length !== 4) {  
            console.log('输入格式错误,请重新输入!');  
            continue;  
        }  
          
        const n = 2; // 因为题目中固定是两道菜  
        const m = parts[2]; // 第二道菜和第二道菜的间隔时间  
        const arr1 = [parts[0], parts[1]]; // 第一道菜的制作时间数组  
        const arr2 = [parts[3], parts[0] + m]; // 第二道菜的制作时间数组,第二道菜开始时间是第一道菜结束时间加间隔时间  
  
        // 设置一个数组,存放每道菜可以吃到的时间  
        const arrTime = [arr1[0] + arr1[1], arr2[0] + arr2[1]];  
  
        // 对数组进行从小到大排序  
        arrTime.sort((a, b) => a - b);  
  
        // 新建一个数组,记录每道菜是否可以吃到,可以吃到标记为true  
        const arrCount = [false, false];  
  
        let next = 0;  
        arrCount[0] = true; // 第一道菜总是可以吃到  
        if (arrTime[1] >= (arrTime[next] + m)) {  
            arrCount[1] = true; // 检查第二道菜是否可以吃到  
        }  
  
        // 计算可以吃到的菜的数量  
        let count = arrCount.filter(canEat => canEat).length;  
  
        // 输出结果  
        console.log(count);  
    }  
  
    // 关闭readline接口  
    rl.close();  
}  
  
// 调用主函数  
main();

八、Python算法源码

# 导入需要的库  
from typing import List  
  
# 主函数  
def main():  
    # 读取用户输入的行长度和数组数量  
    len_per_line = int(input("请输入每行的固定长度: "))  
    num_arrays = int(input("请输入整数数组的数目: "))  
      
    # 读取一行空行(nextInt后留下的)  
    input()  
      
    # 存储所有数组的列表  
    arrays = []  
    max_array_len = 0  
    total_len = 0  
      
    # 读取并处理每个数组  
    for _ in range(num_arrays):  
        # 读取一行,并按逗号分割成字符串列表  
        array_str = input().split(",")  
        arrays.append(array_str)  
        total_len += len(array_str)  
        max_array_len = max(max_array_len, len(array_str))  
      
    # 计算每个数组最多需要截取几次,即遍历次数  
    cycle = max_array_len // len_per_line  
    if max_array_len % len_per_line != 0:  
        cycle += 1  
      
    # 初始化结果列表  
    results = []  
      
    # 遍历所有截取次数  
    for i in range(cycle):  
        # 遍历所有数组  
        for array in arrays:  
            start = i * len_per_line  
            end = (i + 1) * len_per_line  
            size = len(array)  
              
            # 如果开始索引大于数组长度,说明该数组已经取完  
            if start > size - 1:  
                continue  
              
            # 结束索引最大为数组长度  
            if end > size:  
                end = size  
              
            # 取指定长度的子数组  
            results.extend(array[start:end])  
      
    # 输出结果,使用逗号连接  
    print(",".join(results))  
  
# 调用主函数  
if __name__ == "__main__":  
    main()

九、C算法源码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    // 读取输入
    int len, num;
    scanf("%d %d", &len, &num);
    getchar(); // 读取换行符

    char ***arrays = (char ***)malloc(num * sizeof(char **));
    int maxArrayLen = 0;
    int totalLen = 0;
    for (int i = 0; i < num; i++) {
        char line[100];
        fgets(line, sizeof(line), stdin);
        char *token = strtok(line, ",");
        int arrayLen = 0;
        while (token != NULL) {
            arrayLen++;
            token = strtok(NULL, ",");
        }
        arrays[i] = (char **)malloc(arrayLen * sizeof(char *));
        rewind(stdin); // 重置文件指针
        fgets(line, sizeof(line), stdin);
        token = strtok(line, ",");
        for (int j = 0; j < arrayLen; j++) {
            arrays[i][j] = token;
            token = strtok(NULL, ",");
        }
        totalLen += arrayLen;
        maxArrayLen = (arrayLen > maxArrayLen) ? arrayLen : maxArrayLen;
    }

    // 计算每个数组最多需要截取几次,即遍历次数
    int cycle;
    if (maxArrayLen % len == 0) {
        cycle = maxArrayLen / len;
    } else {
        cycle = maxArrayLen / len + 1;
    }

    // 拼接结果数组
    char **results = (char **)malloc(totalLen * sizeof(char *));
    int start, end;
    int resultIndex = 0;
    for (int i = 0; i < cycle; i++) {
        for (int j = 0; j < num; j++) {
            start = i * len;
            end = (i + 1) * len;
            int size = arrayLen;

            // 如果开始index已经大于数组最大,说明该数组取完了
            if (start > size - 1) {
                continue;
            }

            // 结束index最大为size
            if (end > size) {
                end = size;
            }

            // 取指定长度的子数组
            for (int k = start; k < end; k++) {
                results[resultIndex++] = arrays[j][k];
            }
        }
    }

    // 输出结果
    for (int i = 0; i < resultIndex; i++) {
        printf("%s", results[i]);
        if (i < resultIndex - 1) {
            printf(",");
        }
    }
    printf("
");

    // 释放内存
    for (int i = 0; i < num; i++) {
        free(arrays[i]);
    }
    free(arrays);
    free(results);

    return 0;
}

十、C++算法源码

#include <iostream>
#include <vector>
#include <sstream>
#include <algorithm>
#include <iterator>

int main() {
    // 读取输入
    int len, num;
    std::cin >> len >> num; // 行每次读取的固定长度和整数数组的数目
    std::cin.ignore(); // nextInt后有空行,先读取一次

    std::vector<std::vector<std::string>> arrays(num);
    int maxArrayLen = 0;
    int totalLen = 0;
    for (int i = 0; i < num; i++) {
        std::string line;
        std::getline(std::cin, line); // 读取一行
        std::istringstream iss(line);
        std::vector<std::string> array{std::istream_iterator<std::string>{iss}, std::istream_iterator<std::string>{}};
        arrays[i] = array;
        totalLen += array.size();
        maxArrayLen = std::max(maxArrayLen, static_cast<int>(array.size()));
    }

    // 计算每个数组最多需要截取几次,即遍历次数
    int cycle;
    if (maxArrayLen % len == 0) {
        cycle = maxArrayLen / len;
    } else {
        cycle = maxArrayLen / len + 1;
    }

    // 拼接结果数组
    std::vector<std::string> results(totalLen);

    int start, end;
    for (int i = 0; i < cycle; i++) {
        for (const auto& array : arrays) {
            start = i * len;
            end = (i + 1) * len;
            int size = array.size();

            // 如果开始index已经大于数组最大,说明该数组取完了
            if (start > size - 1) {
                continue;
            }

            // 结束index最大为size
            if (end > size) {
                end = size;
            }

            // 取指定长度的子数组
            std::copy(array.begin() + start, array.begin() + end, std::back_inserter(results));
        }
    }
    std::cout << std::join(",", results) << std::endl;
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值