华为OD机试真题 - 猴子吃桃 - 2024 E卷(Java、Python、JavaScript、C、C++合集)

一、题目描述

孙悟空喜欢吃蟠桃,一天他乘守卫蟠桃园的天兵天将离开了而偷偷的来到王母娘娘的蟠桃园偷吃蟠桃。

已知蟠桃园有 N 棵蟠桃树,第 i 棵蟠桃树上有 N[i](大于 0)个蟠桃,天兵天将将在 H(不小于蟠桃树棵数)小时后回来。

孙悟空可以决定他吃蟠桃的速度 K(单位:个/小时),每个小时他会选择一颗蟠桃树,从中吃掉 K 个蟠桃,如果这棵树上的蟠桃数小于 K,他将吃掉这棵树上所有蟠桃,然后这一小时内不再吃其余蟠桃树上的蟠桃。

孙悟空喜欢慢慢吃,但仍想在天兵天将回来前将所有蟠桃吃完。

求孙悟空可以在 H 小时内吃掉所有蟠桃的最小速度 K(K 为整数)。

二、输入描述

从标准输入中读取一行数字,前面数字表示每棵数上蟠桃个数,最后的数字表示天兵天将将离开的时间。

三、输出描述

吃掉所有蟠桃的 最小速度 K(K 为整数)或 输入异常时输出 -1。

四、测试用例

测试用例1

1、输入

3 11 6 7 8

2、输出

4

3、说明

天兵天将8个小时后回来,孙悟空吃掉所有蟠桃的最小速度4。

  1. 第1小时全部吃完第一棵树,吃3个,
  2. 第2小时吃4个,第二棵树剩7个,
  3. 第3小时吃4个,第二棵树剩3个,
  4. 第4小时吃3个,第二棵树吃完,
  5. 第5小时吃4个,第三棵树剩2个,
  6. 第6小时吃2个,第三棵树吃完,
  7. 第7小时吃4个,第4棵树剩3个,
  8. 第8小时吃3个,第4棵树吃完。

测试用例2

1、输入

3 25 6 7 8

2、输出

7

五、解题思路

题目描述有点复杂,多读几遍不难理解,意思就是:

一个小时只能在一棵桃树上吃,如果吃不完,下一个小时继续吃,如果吃完了,就不吃了,但不能去吃下一颗桃树,要守规矩。

  1. 输入几个数,表示每颗树的桃子数量;
  2. 在H个小时内,以最慢的速度将这些桃子全部吃完。

很明显的回溯问题,一个一个找呗,看哪个速度最合适。

六、Java算法源码

public class Test09 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int[] arr = Arrays.stream(sc.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
        // 天兵天将将离开的时间H
        int H = arr[arr.length - 1];

        // 获取每棵数上蟠桃个数
        arr = Arrays.copyOf(arr, arr.length - 1);
        // 从少到多排序
        Arrays.sort(arr);

        int left = 1;
        int right = arr[arr.length - 1];
        while (left < right) {
            int mid = (left + right) / 2;
            // 吃完了,还能慢一点
            if (dfs(arr, H, mid)) {
                right = mid;
            } else {// 没吃完,吃快一点
                left = mid + 1;
            }
        }
        System.out.println(left);
        System.out.println("执行次数:" + num);
    }

    // 记录回溯次数,优化回溯算法
    static int num = 0;
    // 上一次吃完所有桃子的速度
    static int preSpeed = 0;

    private static boolean dfs(int[] arr, int H, int K) {
        int times = 0;
        for (int i = 0; i < arr.length; i++) {
            num++;
            // 以速度K吃完每颗桃树的时间
            times += arr[i] / K;
            if (arr[i] % K != 0) {
                times++;
            }
        }
        return times <= H;
    }
}

七、Python算法源码

def dfs(arr, H, K):
    global num
    times = 0
    for peaches in arr:
        num += 1
        # 计算以速度K吃完每颗桃树的时间
        times += peaches // K
        if peaches % K != 0:
            times += 1
    return times <= H

def main():
    global num
    num = 0
    
    arr = list(map(int, input().split()))
    H = arr[-1]

    # 获取每棵树上蟠桃个数
    arr = arr[:-1]
    
    # 从少到多排序
    arr.sort()

    left = 1
    right = arr[-1]
    
    while left < right:
        mid = (left + right) // 2
        if dfs(arr, H, mid):  # 吃完了,还能慢一点
            right = mid
        else:  # 没吃完,吃快一点
            left = mid + 1

    print(left)
    print("执行次数:", num)

if __name__ == "__main__":
    main()

八、JavaScript算法源码

let num = 0;

function dfs(arr, H, K) {
    let times = 0;
    for (let i = 0; i < arr.length; i++) {
        num++;
        // 以速度K吃完每棵桃树的时间
        times += Math.floor(arr[i] / K);
        if (arr[i] % K !== 0) {
            times++;
        }
    }
    return times <= H;
}

function main() {
    num = 0;

    // 读取输入,并将其转换为整数数组
    let input = prompt("Enter the values separated by spaces: ");
    let arr = input.split(' ').map(Number);

    // 天兵天将将离开的时间H
    let H = arr[arr.length - 1];

    // 获取每棵树上蟠桃个数
    arr = arr.slice(0, arr.length - 1);

    // 从少到多排序
    arr.sort((a, b) => a - b);

    let left = 1;
    let right = arr[arr.length - 1];

    while (left < right) {
        let mid = Math.floor((left + right) / 2);
        if (dfs(arr, H, mid)) {  // 吃完了,还能慢一点
            right = mid;
        } else {  // 没吃完,吃快一点
            left = mid + 1;
        }
    }

    console.log(left);
    console.log("执行次数:" + num);
}

// 执行主函数
main();

九、C算法源码

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

int num = 0;

int dfs(int arr[], int length, int H, int K) {
    int times = 0;
    for (int i = 0; i < length; i++) {
        num++;
        // 以速度K吃完每棵桃树的时间
        times += arr[i] / K;
        if (arr[i] % K != 0) {
            times++;
        }
    }
    return times <= H;
}

int compare(const void *a, const void *b) {
    return (*(int*)a - *(int*)b);
}

int main() {
    num = 0;

    int n;
    printf("请输入数据的数量(包含最后一个时间值): ");
    scanf("%d", &n);

    int arr[n];
    printf("请输入数据(以空格分隔): ");
    for (int i = 0; i < n; i++) {
        scanf("%d", &arr[i]);
    }

    // 天兵天将将离开的时间H
    int H = arr[n - 1];

    // 获取每棵树上蟠桃个数
    n = n - 1; // 更新n为数组长度
    qsort(arr, n, sizeof(int), compare);

    int left = 1;
    int right = arr[n - 1];

    while (left < right) {
        int mid = (left + right) / 2;
        if (dfs(arr, n, H, mid)) {  // 吃完了,还能慢一点
            right = mid;
        } else {  // 没吃完,吃快一点
            left = mid + 1;
        }
    }

    printf("最小速度: %d\n", left);
    printf("执行次数: %d\n", num);

    return 0;
}

十、C++算法源码

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int num = 0;

bool dfs(const vector<int>& arr, int H, int K) {
    int times = 0;
    for (int peaches : arr) {
        num++;
        // 以速度K吃完每棵桃树的时间
        times += peaches / K;
        if (peaches % K != 0) {
            times++;
        }
    }
    return times <= H;
}

int main() {
    num = 0;

    int n;
    cout << "请输入数据的数量(包含最后一个时间值): ";
    cin >> n;

    vector<int> arr(n);
    cout << "请输入数据(以空格分隔): ";
    for (int i = 0; i < n; i++) {
        cin >> arr[i];
    }

    // 天兵天将将离开的时间H
    int H = arr[n - 1];

    // 获取每棵树上蟠桃个数
    arr.pop_back();  // 移除最后一个元素
    sort(arr.begin(), arr.end());

    int left = 1;
    int right = arr.back();

    while (left < right) {
        int mid = (left + right) / 2;
        if (dfs(arr, H, mid)) {  // 吃完了,还能慢一点
            right = mid;
        } else {  // 没吃完,吃快一点
            left = mid + 1;
        }
    }

    cout << "最小速度: " << left << endl;
    cout << "执行次数: " << num << endl;

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值