2064. 分配给商店的最多商品的最小值

【算法题解】最小化最大分配:分配商品到商店的二分查找方案


题目描述

给定 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+x1

将所有商品需要的商店数相加,若总数不超过 n,说明这个 x 是可行的。


解题思路:二分查找 + 贪心判定

由于 x 的取值范围是 [1, max(quantities)]
我们可以用二分查找来确定最小的可行值 x

  1. 设置 left = 1right = max(quantities)
  2. 计算中间值 mid = (left + right) // 2
  3. 调用判定函数 canDistribute(mid) 判断是否可行:
    • 如果可行,尝试缩小上界 right = mid
    • 否则,扩大下界 left = mid + 1
  4. 直到 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 是否能分配完所有商品。
  • 关键技巧:使用二分查找缩小搜索范围,判定函数保证了算法的高效。
  • 该方法广泛适用于这类「最小化最大值」的拆分/分配问题。

如果想进一步优化,可考虑利用数据结构加速,但本题规模下二分+贪心已经足够。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值