Think the problem reversely

Jimmy (xiaoke) Shen
2 min readJun 6, 2021

This week’s (Jun 5, 2021) 4th problem, we can solve it by thinking the problem process reversely.

1889. Minimum Space Wasted From Packaging

A naive approach got TLE

A naive approach is putting the pacakage in a map and traverse each package to see the smallest fit box. And harvest the results.

The time complexity is O(n*m*log m) where n is the length of the packages and m is the maximum length of the box. Since n and m can as large as 10⁵, this solution will get TLE.

typedef long long LL;
const int mod = 1e9+7;
const long long INF = 1e10+6;
class Solution {
public:
int minWastedSpace(vector<int>& packages, vector<vector<int>>& boxes) {
LL ret =INF;
map<int, int> cnt;
for (auto p: packages)cnt[p]++;
for (auto &box: boxes){
sort(box.begin(), box.end());
if (box.back() < cnt.rbegin()->first)continue;
LL thisret = 0;
for (auto [k, v]: cnt) {
auto it = lower_bound(box.begin(), box.end(), k);
thisret += v*(*it - k);
}
ret = min(ret, (LL)thisret);
}
return ret == INF? -1: ret%mod;
}
};

runtime

32 / 41 test cases passed.Status: Time Limit Exceeded

A better way

We can think the problem reversely:

Previous solution is:

for package in packages

for box in boxes

We can try

for box in boxes:

binary search the box’s corresponding location in packages.

The improved algorithm has the complexity of O(m log n) where m is the length of the whole box and n is the length of the packages.

typedef long long LL;
const int mod = 1e9+7;
const long long INF = 1e10+6;
class Solution {
public:
int minWastedSpace(vector<int>& packages, vector<vector<int>>& boxes) {
LL ret = INF, thisret = 0;
sort(packages.begin(), packages.end());
LL sum = accumulate(packages.begin(), packages.end(), 0ll);
for (auto &box: boxes) {
sort(box.begin(), box.end());
if (box.back() < packages.back()) continue;
thisret = 0;
int last = -1;
for (auto &b: box) {
// find the larger than the current box's package location, then the rest part's packages will be all less or equal to the box.
int newidx = upper_bound(packages.begin(), packages.end(), b) - packages.begin();
if (newidx - 1 > last){
thisret += (LL)b*(newidx -1 - last);
last = newidx - 1;
}
}
ret = min(ret, thisret - sum);
}
return ret == INF? -1: ret%mod;
}
};

runtime

Runtime: 292 ms, faster than 87.50% of C++ online submissions for Minimum Space Wasted From Packaging.Memory Usage: 110.1 MB, less than 50.00% of C++ online submissions for Minimum Space Wasted From Packaging.

--

--