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

132 阅读4分钟

问题描述

小M在春游时打算携带尽可能多的巧克力板。她拥有n块巧克力板,每块巧克力的边长为aiai​,重量为ai2ai2​。小M有多个不同大小的背包,每个背包都有一定的最大承重限制。她希望你帮助她计算在每个背包的最大承重范围内,最多可以带走多少块巧克力板。

例如:小M有5块巧克力板,边长分别为1, 2, 2, 4, 5,有5个不同的背包,其最大承重分别为1, 3, 7, 9, 15。对于每个背包,她能装入的巧克力块数分别是1, 1, 2, 3, 3

测试样例

样例1:

输入:n = 5, m = 5, a = [1, 2, 2, 4, 5], queries = [1, 3, 7, 9, 15]
输出:[1, 1, 2, 3, 3]

样例2:

输入:n = 4, m = 3, a = [3, 1, 2, 5], queries = [5, 10, 20]
输出:[2, 2, 3]

样例3:

输入:n = 6, m = 4, a = [1, 3, 2, 2, 4, 6], queries = [8, 12, 18, 25]
输出:[2, 3, 4, 4]

分析

问题理解

小M有若干块巧克力板,每块巧克力的边长为 (a_i),重量为 (a_i^2)。她有多个不同大小的背包,每个背包都有一定的最大承重限制。我们需要计算在每个背包的最大承重范围内,最多可以带走多少块巧克力板。

数据结构选择

  1. 巧克力板列表

    • 输入:一个列表 a,表示每块巧克力板的边长。
    • 输出:一个列表 weights,表示每块巧克力板的重量(即边长的平方)。
  2. 背包列表

    • 输入:一个列表 queries,表示每个背包的最大承重。
    • 输出:一个列表 results,表示每个背包在最大承重范围内最多可以装入的巧克力板数量。

算法步骤

  1. 计算每块巧克力的重量

    • 遍历巧克力板列表 a,计算每块巧克力的重量并存储在 weights 列表中。
  2. 排序巧克力板

    • 按重量从小到大排序 weights 列表,这样我们可以优先选择重量较小的巧克力板。
  3. 处理每个背包的查询

    • 对于每个背包的最大承重 max_weight,从排序后的 weights 列表中选择尽可能多的巧克力板,直到超过背包的承重限制。
    • 记录每个背包最多可以装入的巧克力板数量,并存储在 results 列表中。

难点分析

  1. 排序操作

    • 需要对巧克力板的重量进行排序,以确保我们优先选择重量较小的巧克力板。排序操作的时间复杂度为 (O(n \log n)),其中 (n) 是巧克力板的数量。
  2. 贪心选择

    • 在处理每个背包的查询时,需要使用贪心算法选择尽可能多的巧克力板。这个过程需要遍历排序后的 weights 列表,时间复杂度为 (O(n))。
  3. 多次查询

    • 对于每个背包的查询,都需要重新遍历排序后的 weights 列表。如果有 (m) 个背包,则总的时间复杂度为 (O(m \cdot n))。

代码

def solution(n: int, m: int, a: list, queries: list) -> list:
    # 计算每块巧克力的重量
    weights = [x**2 for x in a]
    
    # 按重量从小到大排序巧克力板
    sorted_weights = sorted(weights)
    
    results = []
    
    # 处理每个背包的查询
    for max_weight in queries:
        current_weight = 0
        count = 0
        
        # 选择尽可能多的巧克力板,直到超过背包的承重限制
        for weight in sorted_weights:
            if current_weight + weight <= max_weight:
                current_weight += weight
                count += 1
            else:
                break
        
        results.append(count)
    
    return results

if __name__ == '__main__':
    print(solution(5, 5, [1, 2, 2, 4, 5], [1, 3, 7, 9, 15]) == [1, 1, 2, 3, 3])
    print(solution(4, 3, [3, 1, 2, 5], [5, 10, 20]) == [2, 2, 3])
    print(solution(6, 4, [1, 3, 2, 2, 4, 6], [8, 12, 18, 25]) == [2, 3, 4, 4])
  • 计算每块巧克力的重量

    • 代码中使用了列表推导式 weights = [x**2 for x in a] 来计算每块巧克力的重量。
  • 按重量从小到大排序巧克力板

    • 代码中使用了 sorted(weights) 来对巧克力板的重量进行排序。
  • 处理每个背包的查询

    • 代码中使用了嵌套的循环来处理每个背包的查询:

      • 外层循环遍历 queries 列表,表示每个背包的最大承重。
      • 内层循环遍历排序后的 sorted_weights 列表,选择尽可能多的巧克力板,直到超过背包的承重限制。
    • 使用贪心算法的思想。

  • 结果存储

    • 代码中使用了 results.append(count) 来存储每个背包最多可以装入的巧克力板数量。