class Solution:
def maxLength(self, ribbons, k):
def count(mid):
return sum(r // mid for r in ribbons)
left, right = 1, max(ribbons)
result = 0
while left <= right:
mid = (left + right) // 2
if count(mid) >= k:
result = mid
left = mid + 1
else:
right = mid - 1
return result
class Solution {
public:
int maxLength(vector<int>& ribbons, int k) {
int left = 1, right = *max_element(ribbons.begin(), ribbons.end());
int result = 0;
auto count = [&](int len) {
int total = 0;
for (int r : ribbons) total += r / len;
return total;
};
while (left <= right) {
int mid = left + (right - left) / 2;
if (count(mid) >= k) {
result = mid;
left = mid + 1;
} else {
right = mid - 1;
}
}
return result;
}
};
class Solution {
public int maxLength(int[] ribbons, int k) {
int left = 1, right = 0;
for (int r : ribbons) right = Math.max(right, r);
int result = 0;
while (left <= right) {
int mid = left + (right - left) / 2;
int count = 0;
for (int r : ribbons) count += r / mid;
if (count >= k) {
result = mid;
left = mid + 1;
} else {
right = mid - 1;
}
}
return result;
}
}
var maxLength = function(ribbons, k) {
let left = 1, right = Math.max(...ribbons);
let result = 0;
const count = (len) => ribbons.reduce((acc, r) => acc + Math.floor(r / len), 0);
while (left <= right) {
const mid = Math.floor((left + right) / 2);
if (count(mid) >= k) {
result = mid;
left = mid + 1;
} else {
right = mid - 1;
}
}
return result;
};
You are given an array ribbons
where each element represents the length of a ribbon, and an integer k
. Your task is to cut the ribbons into pieces such that you get exactly k
or more pieces, and all pieces are of the same positive integer length. You can cut any ribbon as many times as you want or even leave it unused. The goal is to find the maximum possible integer length for these pieces.
k
pieces of that length can be obtained. If it is not possible, return 0.Key Constraints:
At first glance, the problem seems to invite a brute-force approach: try every possible piece length from 1 up to the length of the longest ribbon, and for each, check if you can cut at least k
pieces of that length. However, this is inefficient, especially for large inputs.
On closer inspection, we realize that increasing the piece length will decrease the number of pieces we can get, and vice versa. This monotonic property suggests the use of binary search: we can efficiently home in on the largest possible length by checking, for a given length, whether it's possible to get at least k
pieces.
The key insight is to shift from checking every length (brute-force) to using the binary search technique to minimize the number of checks and speed up the process.
Let's break down the optimized solution step by step:
k
pieces.
mid
, compute how many pieces you can get by dividing each ribbon by mid
(using integer division).k
, it means you can try a longer length, so move the lower bound up.k
, try shorter lengths by moving the upper bound down.ribbon_length // mid
for all ribbons to find how many pieces you can make.
k
pieces. Return this value at the end.
This approach is efficient because each binary search iteration reduces the search space by half, and counting the pieces is a simple linear operation.
Suppose ribbons = [9, 7, 5]
and k = 3
. Let's find the maximum possible length.
The largest length is 5, and we can get exactly 3 pieces of length 5.
The binary search approach is much more efficient and works well even for large arrays and large ribbon lengths.
The Cutting Ribbons problem is elegantly solved using binary search. By leveraging the monotonic relationship between piece length and the number of pieces, we can efficiently find the maximum possible length for the pieces. The key insight is to avoid brute-force enumeration and instead use binary search to minimize the number of checks. This strategy ensures both correctness and efficiency, making the solution suitable for large input sizes.