AI刷题:巧克力板选择问题 | 豆包MarsCode AI刷题

124 阅读3分钟

一. 题目分析

该题是一道兼具二分查找和前缀和的组合题,涉及数组排序和高效查询的组合应用。题目描述如下:

M 正在叉春旅游,想要打包尽可能多的巧克力板。每块巧克力板的边长为 a[i],重量为 a[i]^2。M 有多个背包,每个背包有一个最大承重限制 queries[j]。对于每个背包,我们需要确定在不超过承重限制的情况下,最多可以装上多少块巧克力板。

输入说明

  • n:巧克力板的数量。
  • m:背包的数量。
  • a:巧克力板的边长数组。
  • queries:背包的最大承重限制数组。

输出说明:对于每个背包,输出一个整数,表示最多可以装上的巧克力板数量。

二. 解题思路

第一步:计算巧克力重量

每块巧克力板的重量可以通过边长的应用计算得到:

  • weight[i] = a[i]^2

第二步:排序和前缀和

为了高效处理重量查询:

  • 将巧克力重量排序为升序。

  • 计算前缀和数组,以便快速获取多块巧克力板的积累重量。前缀和数组 prefix[i] 定义为:

    prefix[i] = Σ (weight[j]) 对于 j 从 0 到 i

第三步:二分查找

对于每个背包的承重限制,需要找出最多可以装上多少块巧克力板:

  • 在前缀和数组中使用二分查找到第一个超过这个承重限制的位置。
  • 该位置之前的所有巧克力板都在承重范围内。

第四步:优化考虑

  • 排序和前缀和:通过将巧克力重量排序,使我们可以利用二分查找,加快解决。
  • 二分查找:这一步可以大幅减少确定最多装上的巧克力板的时间。

三. 算法步骤

  1. 计算重量:根据巧克力板的边长计算每个巧克力板的重量。

  2. 排序和前缀和

    • 将重量数组按升序排序。
    • 计算前缀和数组,记录到每个点的积累重量。
  3. 二分查找

    • 对于每个背包的承重限制,使用二分查找到第一个超过这个限制的前缀和。
  4. 输出结果:返回每个背包可以装上的巧克力板数量。

四. 示例分析

输入示例

  • n = 5, m = 5, a = [1, 2, 2, 4, 5], queries = [1, 3, 7, 9, 15]

详细步骤

  1. 计算巧克力重量

    weights = [1, 4, 4, 16, 25]

  2. 排序 (升序排序)

    sorted_weights = [1, 4, 4, 16, 25]

  3. 前缀和计算

    prefix = [1, 5, 9, 25, 50]

  4. 查询结果

    • queries[0] = 1:二分查找得到 prefix[0] = 1,结果为 1
    • queries[1] = 3:二分查找得到 prefix[0] = 1,结果为 1
    • queries[2] = 7:二分查找得到 prefix[1] = 5,结果为 2
    • queries[3] = 9:二分查找得到 prefix[2] = 9,结果为 3
    • queries[4] = 15:二分查找得到 prefix[2] = 9,结果为 3

输出[1, 1, 2, 3, 3]

五. 代码实现

下面是完整的 Python 实现:

def solution(n: int, m: int, a: list, queries: list) -> list:
    # write code here
    weights = [x ** 2 for x in a]
    weights.sort()
    prefix = [0] * n
    prefix[0] = weights[0]
    for i in range(1, n):
        prefix[i] = prefix[i - 1] + weights[i]
    
    result = []
    
    for max_weight in queries:
        left, right = 0, n - 1
        while left <= right:
            mid = (left + right) // 2
            if prefix[mid] <= max_weight:
                left = mid + 1
            else:
                right = mid - 1
        
        result.append(right + 1)  
    
    return result


六. 复杂度分析

  • 时间复杂度

    • 重量计算:O(n)
    • 排序:O(nlogn)
    • 前缀和计算:O(n)
    • 二分查找:每次查询 O(logn),总共 m 次查询:O(mlogn)
    • 总时间复杂度O(nlog n + mlogn)
  • 空间复杂度

    • 存储重量数组和前缀和数组:O(n)

七. 个人思考与总结

  • 核心解决方案:解决这个问题的关键在于利用排序和前缀和来优化重量的计算。通过二分查找,确定可装巧克力板的数量复杂度从线性降低到对数级。
  • 优化方向:如果背包承重范围超过很大,可考虑使用分块或者指数表进一步优化查询过程。