【算法题解】最小化最大分配:分配商品到商店的二分查找方案
题目描述
给定 n 间零售商店和 m 种不同种类的商品。
其中每种商品的数量用数组 quantities 表示,quantities[i] 表示第 i 种商品的总数。
分配规则:
- 每间商店最多只能拥有 一种商品(但可以拥有多件该种商品)。
- 分配后,每间商店分配的商品数目可以是 0(即允许不分配商品的商店)。
- 目标是要使得所有商店中,分配商品数目的最大值
x尽可能小。
你需要返回这个最小可能的最大分配值 x。
举例说明
- 输入:
n = 6, quantities = [11, 6]
输出:3
解释:- 商品种类0的11件分配到4间商店,分配数量分别是 [2, 3, 3, 3]
- 商品种类1的6件分配到2间商店,分配数量分别是 [3, 3]
- 所有商店中最大商品数是3,且无法更小。
- 输入:
n = 7, quantities = [15, 10, 10]
输出:5
解释:- 种类0分到3间,每间5件
- 种类1分到2间,每间5件
- 种类2分到2间,每间5件
- 最大值为5。
- 输入:
n = 1, quantities = [100000]
输出:100000
解释:- 只有一间商店,必须全部放进去。
题目分析
题目的核心限制是:
- 每间商店只能放一种商品类别;
- 但是一个类别的商品可以拆分到多间商店;
- 我们要最小化“任何一间商店最多有多少商品”的最大值。
关键问题转换
给定一个最大容量 x,判断是否能用 n 个商店,把所有商品都分完。
对于第 i 种商品,数量为 q,每间商店最多放 x 件,那么该商品需要的商店数是:
needed=⌈qx⌉=q+x−1x\text{needed} = \lceil \frac{q}{x} \rceil = \frac{q + x - 1}{x}needed=⌈xq⌉=xq+x−1
将所有商品需要的商店数相加,若总数不超过 n,说明这个 x 是可行的。
解题思路:二分查找 + 贪心判定
由于 x 的取值范围是 [1, max(quantities)],
我们可以用二分查找来确定最小的可行值 x:
- 设置
left = 1,right = max(quantities)。 - 计算中间值
mid = (left + right) // 2。 - 调用判定函数
canDistribute(mid)判断是否可行:- 如果可行,尝试缩小上界
right = mid。 - 否则,扩大下界
left = mid + 1。
- 如果可行,尝试缩小上界
- 直到
left == right,返回这个值。
代码实现示例(Python)
from typing import List
class Solution:
def minimizedMaximum(self, n: int, quantities: List[int]) -> int:
def canDistribute(x: int) -> bool:
shops_needed = 0
for q in quantities:
shops_needed += (q + x - 1) // x # 计算需要多少商店
if shops_needed > n: # 超过总商店数,说明不可行
return False
return True
left, right = 1, max(quantities)
while left < right:
mid = (left + right) // 2
if canDistribute(mid):
right = mid
else:
left = mid + 1
return left
复杂度分析
- 判定函数
canDistribute对所有商品做一次遍历,时间复杂度为O(m),m是商品种类数。 - 二分查找最多需要
O(log(max(quantities)))次判定。 - 总时间复杂度为:
O(m * log(max(quantities))),对题目给定的输入规模(最大10^5)是可接受的。
代码流程示意
假设 quantities = [11, 6], n = 6,二分查找范围为 [1, 11]:
- mid = 6,判定需要商店数:
- 商品0:11件,每间商店最多6件,商店数 = ceil(11/6) = 2
- 商品1:6件,每间商店最多6件,商店数 = 1
- 总共需要商店数 = 3 <= 6,成立,尝试减小范围
right = 6
- mid = 3,判定:
- 商品0:ceil(11/3) = 4
- 商品1:ceil(6/3) = 2
- 总共需要6,等于n,成立,
right = 3
- mid = 2,判定:
- 商品0:ceil(11/2) = 6
- 商品1:ceil(6/2) = 3
- 总共9 > 6,不成立,
left = 3
- 结束,返回
3
总结与思考
- 核心难点:如何判断某个最大分配数
x是否能分配完所有商品。 - 关键技巧:使用二分查找缩小搜索范围,判定函数保证了算法的高效。
- 该方法广泛适用于这类「最小化最大值」的拆分/分配问题。
如果想进一步优化,可考虑利用数据结构加速,但本题规模下二分+贪心已经足够。
2166

被折叠的 条评论
为什么被折叠?



