■ 题目描述
【最短木板长度】
小明有 n 块木板,第 i ( 1 ≤ i ≤ n ) 块木板长度为 ai。
小明买了一块长度为 m 的木料,这块木料可以切割成任意块,
拼接到已有的木板上,用来加长木板。
小明想让最短的模板尽量长。
请问小明加长木板后,最短木板的长度可以为多少?
# -*- coding:utf-8 -*-
"""
流程分析:
1. 只有一个板子的时候直接加;
2. 有2个板子的时候:
短板+m <= 长板 时 => min_len = 短板+m;
短板+m>长版 时 => min_len = 长版+(m-(长版-短板))//2
3. 超过2个板子
从最小阶级差开始,一层一层计算:
可能一根都补不齐;
可能满足一部分;
可能补到当前最高板子还多;
"""
from collections import Counter
def compute_min_len(n, m):
if len(n) == 1:
return n[0] + m
elif len(n) == 2:
# 排序用于区分大小值
n1 = sorted(n)
# 两板长度差距
p_dis = n1[1] - n1[0]
if m <= p_dis:
return n1[0] + m
else:
return n1[1] + (m - (n1[1] - n1[0])) // 2
else:
# 排序用于区分大小值 Set用于更好的区分不同长度板子的差异
set_n = sorted(list(set(n)))
# Counter能更好的计算不同板长的数量 用于后续补平计算
counter_n = Counter(n)
i = 0
min_len = set_n[0]
while i < len(set_n) - 1:
# 两板长度差距
p_dis = set_n[i + 1] - set_n[i]
# 短板数量
p_count = counter_n[set_n[i]]
# m 是否能补平所有短板
if m // p_count <= p_dis:
if m // p_count >= 1:
min_len += m // p_count
else:
min_len
m = 0
break
else:
min_len = set_n[i] + p_dis
counter_n[set_n[i + 1]] += p_count
m -= p_dis * counter_n[set_n[i]]
del counter_n[set_n[i]]
i += 1
# m 板很长,补平所有板到最高时,还能继续加板长
if m:
min_len += m // counter_n[set_n[-1]]
return min_len
# Test Cases Part.
# Only 1
n, m = [1], 110
min_len = compute_min_len(n, m)
print(min_len, min_len == 111)
# Only 2 补不平
n, m = [1, 103], 100
min_len = compute_min_len(n, m)
print(min_len, min_len == 101)
# Only 2 补平超
n, m = [1, 103], 110
min_len = compute_min_len(n, m)
print(min_len, min_len == 107)
# Multi 无补平
n, m = [1, 1, 5, 7, 8, 18], 1
min_len = compute_min_len(n, m)
print(min_len, min_len == 1)
# Multi 部分补平
n, m = [1, 1, 5, 7, 8, 18], 2
min_len = compute_min_len(n, m)
print(min_len, min_len == 2)
n, m = [1, 1, 5, 7, 8, 18], 10
min_len = compute_min_len(n, m)
print(min_len, min_len == 5)
# Multi 超过
n, m = [1, 1, 5, 7, 8, 18], 100
min_len = compute_min_len(n, m)
print(min_len, min_len == 23)
🎉如果对你有所帮助,可以点赞、关注、收藏起来,不然下次就找不到了🎉
【点赞】⭐️⭐️⭐️⭐️⭐️
【关注】⭐️⭐️⭐️⭐️⭐️
【收藏】⭐️⭐️⭐️⭐️⭐️
Thanks for watching.
–Kenny