leetcode
leetcode 1651 ~ 1700
装包裹的最小浪费空间

装包裹的最小浪费空间

难度:

标签:

题目描述

代码结果

运行时间: 183 ms, 内存: 35.2 MB


/*
 * 思路:
 * 1. 对packages和boxes的每个供应商的箱子分别进行排序。
 * 2. 使用Java Stream API来处理每个供应商的箱子,计算最小浪费空间。
 * 3. 对于每个包裹,找到能容纳它的最小箱子。
 * 4. 累计每个箱子的浪费空间,最后取最小浪费空间。
 * 5. 如果存在无法放入的包裹,返回-1。
 */

import java.util.Arrays;
import java.util.stream.IntStream;

public class MinWasteSpaceStream {
    public int minWastedSpace(int[] packages, int[][] boxes) {
        Arrays.sort(packages);
        long mod = 1000000007;
        long totalPackageSize = IntStream.of(packages).asLongStream().sum();

        long minWaste = Arrays.stream(boxes)
                .map(box -> {
                    Arrays.sort(box);
                    if (box[box.length - 1] < packages[packages.length - 1]) {
                        return Long.MAX_VALUE;
                    }
                    long waste = 0;
                    int i = 0;
                    for (int b : box) {
                        int j = i;
                        while (j < packages.length && packages[j] <= b) {
                            j++;
                        }
                        waste += (long) (j - i) * b;
                        i = j;
                    }
                    return waste - totalPackageSize;
                })
                .min()
                .orElse(Long.MAX_VALUE);

        return minWaste == Long.MAX_VALUE ? -1 : (int) (minWaste % mod);
    }
}

解释

方法:

此题解利用前缀和和排序来最小化浪费空间。首先,对包裹数组进行排序,并计算包裹尺寸的频率(f数组)和前缀和(g数组)。然后,对于每个供应商提供的箱子,按箱子尺寸排序,使用二分查找方法寻找每个包裹可以放入的最小箱子。计算每个箱子的浪费空间并累加,最后选取浪费空间最小的供应商。如果某个供应商的最大箱子尺寸小于最大包裹尺寸,则此供应商不能装下所有包裹。该算法针对每个供应商计算浪费空间,最后返回最小值。

时间复杂度:

O(m(b log b + b log n))

空间复杂度:

O(biggest)

代码细节讲解

🦆
在题解中提到的前缀和数组`g`是如何计算的,能否详细解释其作用和计算方法?
在题解中,前缀和数组`g`是用于快速计算某个范围内包裹尺寸总和的工具。首先,我们创建一个频率数组`f`,其中`f[i]`表示尺寸为`i`的包裹的数量。然后,前缀和数组`g`的每个元素`g[i]`存储了所有小于等于`i`尺寸的包裹数量的累加和。具体计算方法是:对于`g`的每个元素,`g[i]`等于`g[i-1]`加上`f[i]`。这样,`g[i]`就能在O(1)时间内给出任何尺寸范围的包裹数量总和,这对于后续计算每个箱子可以装载的包裹数量极为关键和有效。
🦆
题解中使用的二分查找方法是如何应用的?具体是在什么情况下使用,以及它如何帮助优化查找最小箱子尺寸?
尽管题解中没有直接使用二分查找方法,但通常在类似的问题中,二分查找可以用来在已排序的箱子数组中快速找到能够容纳当前考虑的包裹尺寸的最小箱子。具体来说,对于每个包裹尺寸,我们可以使用二分查找在箱子数组中找到第一个大于等于该尺寸的箱子。这样可以确保包裹被放入尽可能小的箱子中,从而最小化浪费空间。在本题解中,通过对箱子进行排序并顺序遍历,实现了类似的效果,即为每个包裹尺寸段找到合适的箱子。
🦆
题解最后的返回结果使用了模运算`(10 ** 9 + 7)`,这里的模运算是基于什么考虑?
模运算`(10 ** 9 + 7)`在编程竞赛和许多编程问题中常用来防止整数溢出,同时也用于保持结果的规模可控,使其在一定的范围内。数字`10 ** 9 + 7`是一个大质数,常用作模数,因为它可以减小哈希冲突的可能性,并且在大多数编程语言中不会导致整数溢出。在这个题解中,考虑到可能需要处理大量的数据和大的数值计算,使用模运算可以有效避免结果超出标准整数范围的问题。

相关问题