【华为OD-E卷-木板 100分(python、java、c++、js、c)】

【华为OD-E卷-木板 100分(python、java、c++、js、c)】

题目

小明有 n 块木板,第 i ( 1 ≤ i ≤ n ) 块木板长度为 ai。

小明买了一块长度为 m 的木料,这块木料可以切割成任意块,拼接到已有的木板上,用来加长木板。

小明想让最短的模板尽量长。请问小明加长木板后,最短木板的长度可以为多少?

输入描述

  • 输入的第一行包含两个正整数, n ( 1 ≤ n ≤ 10^3 ), m ( 1 ≤ m ≤ 10^6 ),n 表示木板数, m 表示木板长度。

输入的第二行包含 n 个正整数, a1, a2,...an ( 1 ≤ ai ≤ 10^6 )

输出描述

  • 输出的唯一一行包含一个正整数,表示加长木板后,最短木板的长度最大可以为多少?

用例

用例一:
输入:
5 3
4 5 3 5 5
输出:
5
用例二:
输入:
5 2
4 5 3 5 5
输出:
4

python解法

  • 解题思路:
  • 本题的目的是找到一个最大长度,使得我们可以通过给定的操作数量 m 来调整数组 a 中的元素,使得所有元素都至少达到该长度。每次操作可以增加某个元素的值。我们希望通过二分法来高效地找到这个最大长度。

具体步骤:

输入分析:首先,输入的是两个整数 n 和 m,分别表示数组 a 的长度和我们可以进行的操作次数。接着输入一个整数列表 a,表示数组的初始值。

核心问题:我们需要判断是否可以通过最多 m 次操作将所有元素增加到某个长度 L(即 L 为数组中的最小值)。为了检查是否能达到某个长度 L,我们可以计算将每个元素增加到 L 所需的操作次数。如果总操作次数不超过 m,则说明可以实现。

二分查找:为了快速找到最大长度,可以用二分查找:

low 初始化为数组中的最小值,high 初始化为数组中的最大值加上 m,因为最多可以将数组元素增加 m。

在二分查找过程中,每次判断当前中点 mid 是否能通过 m 次操作实现。如果能,则尝试增大 mid;如果不能,则减小 mid。

判断函数:can_achieve_length 用于判断是否能将所有元素至少调整到某个长度 length,它的核心是计算每个元素需要增加多少才能达到该长度,并判断是否总操作数不超过 m。

python 复制代码
n, m = map(int, input().split())  # 读取n和m,n是数组的长度,m是可以进行的操作次数
a = list(map(int, input().split()))  # 读取数组a

# 判断是否能通过m次操作将所有元素调整到至少length的值
def can_achieve_length(length, a, m):
    needed = sum(max(0, length - x) for x in a)  # 计算所有元素增加到length所需要的操作次数
    return needed <= m  # 如果操作次数不超过m,则返回True

# 利用二分查找找到最大长度
def find_max_length(a, m):
    low, high = min(a), max(a) + m  # 初始范围,最小值是数组的最小元素,最大值是数组最大值加上m
    best = low  # 保存当前找到的最佳长度

    while low <= high:  # 二分查找
        mid = (low + high) // 2  # 计算中间值
        if can_achieve_length(mid, a, m):  # 如果可以通过m次操作使所有元素至少为mid
            best = mid  # 更新最佳长度
            low = mid + 1  # 尝试寻找更大的值
        else:
            high = mid - 1  # 尝试寻找更小的值

    return best  # 返回找到的最大长度

print(find_max_length(a, m))  # 输出结果

java解法

  • 解题思路
java 复制代码
更新中

C++解法

  • 解题思路
cpp 复制代码
更新中

C解法

解题思路

c 复制代码
更新中

JS解法

解题思路

  • 这道题目要求我们找到一个最大值,使得通过至多 m 次操作,可以将数组 a 中的所有元素调整到至少达到这个值。每次操作可以增加数组元素的值。为了高效地找到这个最大值,我们可以利用 二分查找 的方法。

具体步骤:

输入分析:输入的第一个值是 n(数组的长度),第二个是 m(最多可以进行的操作次数)。接着输入数组 a,其元素表示需要调整的值。

核心问题:对于给定的 m 次操作,能否将数组的所有元素至少增加到某个长度 mid。如果每个元素都小于 mid,就需要增加相应的差值。目标是找出最大的 mid,使得通过至多 m 次操作就能将数组所有元素调整到至少 mid。

二分查找:我们可以通过二分查找来找到这个最大长度 mid,从 low = min(a) 到 high = max(a) + m。每次计算 mid,并判断是否能通过 m 次操作达到这个长度。如果能,则说明可以尝试更大的 mid,否则减小 mid。

判断函数:在每一次的二分查找中,我们需要计算将所有元素调整到 mid 所需的总操作次数,判断是否不超过 m。

javascript 复制代码
// 最大长度查找函数
function maxMinLength(m, a) {
    let low = Math.min(...a);  // 初始时,low为数组a中的最小值
    let high = Math.max(...a) + m;  // high为数组a中的最大值加上操作次数m

    while (low < high) {  // 二分查找
        const mid = Math.floor((low + high + 1) / 2);  // 计算中点值,向上取整
        const needed = a.reduce((sum, length) => {  // 计算将所有元素调整到mid所需的操作次数
            return sum + Math.max(0, mid - length);  // 对于小于mid的元素,计算差值
        }, 0);

        if (needed <= m) {  // 如果操作次数不超过m,说明可以尝试更大的mid
            low = mid;  // 更新low值
        } else {  // 否则,减少mid
            high = mid - 1;
        }
    }

    return low;  // 最终返回的low即为最大能达到的长度
}

// 读取输入的部分
const readline = require('readline');
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

let input = [];

rl.on('line', (line) => {
    input.push(line);  // 逐行读取输入
}).on('close', () => {
    const [n, m] = input[0].split(' ').map(Number);  // 解析n和m
    const a = input[1].split(' ').map(Number);  // 解析数组a
    console.log(maxMinLength(m, a));  // 调用函数输出结果
});

注意:

如果发现代码有用例覆盖不到的情况,欢迎反馈!会在第一时间修正,更新。
解题不易,如对您有帮助,欢迎点赞/收藏

相关推荐
学会沉淀。几秒前
Docker学习
java·开发语言·学习
如若1232 分钟前
对文件内的文件名生成目录,方便查阅
java·前端·python
ragnwang18 分钟前
C++ Eigen常见的高级用法 [学习笔记]
c++·笔记·学习
西猫雷婶31 分钟前
python学opencv|读取图像(二十一)使用cv2.circle()绘制圆形进阶
开发语言·python·opencv
初晴~32 分钟前
【Redis分布式锁】高并发场景下秒杀业务的实现思路(集群模式)
java·数据库·redis·分布式·后端·spring·
老刘莱国瑞1 小时前
STM32 与 AS608 指纹模块的调试与应用
python·物联网·阿里云
黑胡子大叔的小屋1 小时前
基于springboot的海洋知识服务平台的设计与实现
java·spring boot·毕业设计
ThisIsClark1 小时前
【后端面试总结】深入解析进程和线程的区别
java·jvm·面试
一只敲代码的猪2 小时前
Llama 3 模型系列解析(一)
大数据·python·llama
雷神乐乐2 小时前
Spring学习(一)——Sping-XML
java·学习·spring