You are given an array ribbons
of integer lengths. You are also given an integer k
representing the number of ribbon pieces you want to obtain. You can cut each of the ribbons into any number of pieces of the same length. For example, a ribbon of length 5 can be cut into two pieces of length 2 and have length 1 remaining, or into five pieces of length 1. Your goal is to find the maximum integer length you can get for the ribbon pieces such that you can obtain at least k
pieces.
For instance:
ribbons = [1, 2, 3, 4, 5]
and k = 5
, the maximum length is 2, as you can obtain two pieces from ribbon of length 4 and two pieces from the ribbon of length 5 and 1 each from ribbons of length 1 and length 2 and length 3.ribbons = [7, 5, 9]
and k = 4
, the maximum length is 4.ribbons = [9, 7, 5]
and k = 6
, the maximum length is 3.ribbons = [1, 2, 3]
and k = 7
, return 0 because we cannot obtain at least k=7
ribbons pieces.Write a function that takes the ribbons
array and the integer k
as input and returns the maximum possible length of the ribbon pieces.
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
To solve the ribbon cutting problem using brute force, we systematically try out every possible length for the cut ribbons. We see if a particular length allows us to cut enough ribbons from the given pieces to satisfy the requirement.
Here's how the algorithm would work step-by-step:
def cutting_ribbons_brute_force(ribbon_lengths, required_ribbons):
max_length = 0
for ribbon_length in ribbon_lengths:
max_length = max(max_length, ribbon_length)
longest_possible_length = 0
# Iterate through all possible ribbon lengths
for current_length in range(1, max_length + 1):
number_of_ribbons = 0
for ribbon_length in ribbon_lengths:
# Calculate how many ribbons of current_length can be cut
number_of_ribbons += ribbon_length // current_length
# If enough ribbons can be cut, update answer
if number_of_ribbons >= required_ribbons:
# Store the largest length that yields enough ribbons
longest_possible_length = current_length
return longest_possible_length
To efficiently find the longest ribbon piece we can cut, we'll use a process of guessing a length and then checking if we can make enough pieces of that length. We refine our guess based on whether we could make enough pieces or not, eventually zeroing in on the best possible length.
Here's how the algorithm would work step-by-step:
def cutting_ribbons(ribbon_lengths, required_pieces):
shortest_ribbon = 1
longest_ribbon = max(ribbon_lengths)
while shortest_ribbon <= longest_ribbon:
possible_ribbon_length = (shortest_ribbon + longest_ribbon) // 2
number_of_pieces = 0
for ribbon_length in ribbon_lengths:
number_of_pieces += ribbon_length // possible_ribbon_length
# If enough pieces, increase the possible ribbon length.
if number_of_pieces >= required_pieces:
shortest_ribbon = possible_ribbon_length + 1
# Otherwise, decrease the possible ribbon length.
else:
longest_ribbon = possible_ribbon_length - 1
# Need to return the longest valid length.
return longest_ribbon
Case | How to Handle |
---|---|
Empty ribbons array | Return 0, as no ribbon can be cut. |
All ribbon lengths are 0 | If k > 0, return 0; if k == 0, return maximum integer value (or appropriate error if undefined). |
k is 0 | Return the maximum possible length (longest ribbon), or handle it as a special valid case if needed. |
k is very large, greater than sum of lengths | The binary search for the length can converge to 0 if the target number of pieces is too large, so handle this scenario returning 0. |
Ribbon lengths are very large numbers, leading to integer overflow in the count calculation | Use a data type with a larger range (e.g., long) to store the number of pieces calculated in the count function. |
Ribbon lengths contain floating point values. | The problem specified integers, but if floats are permitted then set the correct precision for comparison in the binary search and count functions. |
Maximum ribbon length is 1 and k is greater than the number of ribbons | Handle this case by returning 1 if the number of ribbons is greater or equal to k, and 0 if otherwise. |
One ribbon length is extremely large and k is 1 | If k is 1, then return the maximum ribbon length. |