Problem

You have n packages that you are trying to place in boxes, one package in each box. There are m suppliers that each produce boxes of different sizes (with infinite supply). A package can be placed in a box if the size of the package is less than or equal to the size of the box.

The package sizes are given as an integer array packages, where packages[i] is the size of the ith package. The suppliers are given as a 2D integer array boxes, where boxes[j] is an array of box sizes that the jth supplier produces.

You want to choose a single supplier and use boxes from them such that the total wasted space is minimized. For each package in a box, we define the space wasted to be size of the box - size of the package. The total wasted space is the sum of the space wasted in all the boxes.

  • For example, if you have to fit packages with sizes [2,3,5] and the supplier offers boxes of sizes [4,8], you can fit the packages of size-2 and size-3 into two boxes of size-4 and the package with size-5 into a box of size-8. This would result in a waste of (4-2) + (4-3) + (8-5) = 6.

Return _theminimum total wasted space by choosing the box supplier optimally , or _-1 _if it isimpossible to fit all the packages inside boxes. _Since the answer may be large , return it modulo109 + 7.

Examples

Example 1

1
2
3
4
Input: packages = [2,3,5], boxes = [[4,8],[2,8]]
Output: 6
Explanation: It is optimal to choose the first supplier, using two size-4 boxes and one size-8 box.
The total waste is (4-2) + (4-3) + (8-5) = 6.

Example 2

1
2
3
Input: packages = [2,3,5], boxes = [[1,4],[2,3],[3,4]]
Output: -1
Explanation: There is no box that the package of size 5 can fit in.

Example 3

1
2
3
4
Input: packages = [3,5,8,10,11,12], boxes = [[12],[11,9],[10,5,14]]
Output: 9
Explanation: It is optimal to choose the third supplier, using two size-5 boxes, two size-10 boxes, and two size-14 boxes.
The total waste is (5-3) + (5-5) + (10-8) + (10-10) + (14-11) + (14-12) = 9.

Constraints

  • n == packages.length
  • m == boxes.length
  • 1 <= n <= 10^5
  • 1 <= m <= 10^5
  • 1 <= packages[i] <= 10^5
  • 1 <= boxes[j].length <= 10^5
  • 1 <= boxes[j][k] <= 10^5
  • sum(boxes[j].length) <= 10^5
  • The elements in boxes[j] are distinct.

Solution

Intuition

For each supplier, sort their box sizes. For each package, assign it to the smallest box that can fit it (binary search). Calculate the total waste for each supplier and choose the minimum.

Approach

  1. Sort packages.
  2. For each supplier:
    • Sort their box sizes.
    • If the largest box can’t fit the largest package, skip.
    • For each box size, use binary search to find the range of packages that fit.
    • Accumulate waste.
  3. Return the minimum waste modulo 1e9+7, or -1 if impossible.

Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <algorithm>
class Solution {
public:
    int minWastedSpace(vector<int>& packages, vector<vector<int>>& boxes) {
        sort(packages.begin(), packages.end());
        long res = LONG_MAX, total = 0;
        for (int p : packages) total += p;
        for (auto& b : boxes) {
            sort(b.begin(), b.end());
            if (b.back() < packages.back()) continue;
            long waste = 0, prev = 0;
            for (int size : b) {
                auto it = upper_bound(packages.begin()+prev, packages.end(), size);
                int cnt = it - packages.begin() - prev;
                waste += (long)size * cnt;
                prev += cnt;
            }
            if (prev == packages.size()) res = min(res, waste - total);
        }
        return res == LONG_MAX ? -1 : res % 1000000007;
    }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import "sort"
func minWastedSpace(packages []int, boxes [][]int) int {
    sort.Ints(packages)
    total := 0
    for _, p := range packages { total += p }
    res := int64(1<<62)
    for _, b := range boxes {
        sort.Ints(b)
        if b[len(b)-1] < packages[len(packages)-1] { continue }
        waste, prev := int64(0), 0
        for _, size := range b {
            i := sort.SearchInts(packages[prev:], size+1) + prev
            cnt := i - prev
            waste += int64(size) * int64(cnt)
            prev = i
        }
        if prev == len(packages) && waste-int64(total) < res {
            res = waste-int64(total)
        }
    }
    if res == int64(1<<62) { return -1 }
    return int(res%1000000007)
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.util.*;
class Solution {
    public int minWastedSpace(int[] packages, List<List<Integer>> boxes) {
        Arrays.sort(packages);
        long total = 0, res = Long.MAX_VALUE;
        for (int p : packages) total += p;
        for (List<Integer> b : boxes) {
            Collections.sort(b);
            if (b.get(b.size()-1) < packages[packages.length-1]) continue;
            long waste = 0; int prev = 0;
            for (int size : b) {
                int i = Arrays.binarySearch(packages, prev, packages.length, size+1);
                if (i < 0) i = -i-1;
                int cnt = i - prev;
                waste += (long)size * cnt;
                prev = i;
            }
            if (prev == packages.length) res = Math.min(res, waste-total);
        }
        return res == Long.MAX_VALUE ? -1 : (int)(res%1000000007);
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
    fun minWastedSpace(packages: IntArray, boxes: List<List<Int>>): Int {
        packages.sort()
        val total = packages.sumOf { it.toLong() }
        var res = Long.MAX_VALUE
        for (b in boxes) {
            val box = b.sorted()
            if (box.last() < packages.last()) continue
            var waste = 0L; var prev = 0
            for (size in box) {
                val i = packages.binarySearch(size+1, prev, packages.size)
                val idx = if (i < 0) -i-1 else i
                val cnt = idx - prev
                waste += size.toLong() * cnt
                prev = idx
            }
            if (prev == packages.size) res = minOf(res, waste-total)
        }
        return if (res == Long.MAX_VALUE) -1 else (res%1000000007).toInt()
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
from bisect import bisect_right
class Solution:
    def minWastedSpace(self, packages: list[int], boxes: list[list[int]]) -> int:
        packages.sort()
        total = sum(packages)
        res = float('inf')
        for b in boxes:
            b.sort()
            if b[-1] < packages[-1]: continue
            waste, prev = 0, 0
            for size in b:
                i = bisect_right(packages, size, prev)
                cnt = i - prev
                waste += size * cnt
                prev = i
            if prev == len(packages):
                res = min(res, waste-total)
        return -1 if res == float('inf') else res%1000000007
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
impl Solution {
    pub fn min_wasted_space(packages: Vec<i32>, boxes: Vec<Vec<i32>>) -> i32 {
        let mut packages = packages;
        packages.sort();
        let total: i64 = packages.iter().map(|&x| x as i64).sum();
        let mut res = i64::MAX;
        for mut b in boxes {
            b.sort();
            if *b.last().unwrap() < *packages.last().unwrap() { continue; }
            let mut waste = 0i64; let mut prev = 0;
            for &size in &b {
                let i = match packages[prev..].binary_search(&(size+1)) {
                    Ok(idx) => prev+idx,
                    Err(idx) => prev+idx,
                };
                let cnt = i - prev;
                waste += size as i64 * cnt as i64;
                prev = i;
            }
            if prev == packages.len() { res = res.min(waste-total); }
        }
        if res == i64::MAX { -1 } else { (res%1_000_000_007) as i32 }
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
    minWastedSpace(packages: number[], boxes: number[][]): number {
        packages.sort((a,b)=>a-b);
        const total = packages.reduce((a,b)=>a+b,0);
        let res = Number.MAX_SAFE_INTEGER;
        for (const b of boxes) {
            b.sort((a,b)=>a-b);
            if (b[b.length-1] < packages[packages.length-1]) continue;
            let waste = 0, prev = 0;
            for (const size of b) {
                let i = prev;
                while (i < packages.length && packages[i] <= size) i++;
                const cnt = i - prev;
                waste += size * cnt;
                prev = i;
            }
            if (prev === packages.length) res = Math.min(res, waste-total);
        }
        return res === Number.MAX_SAFE_INTEGER ? -1 : res%1000000007;
    }
}

Complexity

  • ⏰ Time complexity: O(n log n + m k log k) — Sort packages and boxes, binary search for each box size.
  • 🧺 Space complexity: O(n + k) — For sorting and temporary arrays.