Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Program to find maximum length of k ribbons of same length in Python
Suppose we have a list of positive numbers representing ribbon lengths and a value k. We can cut the ribbons as many times as we want, and we need to find the largest length r such that we can have k ribbons of length r. If no such solution exists, return -1.
So, if the input is like ribbons = [1, 2, 5, 7, 15] and k = 5, then the output will be 5. We can cut the ribbon of size 15 into 3 pieces of length 5 each, cut the ribbon of size 7 into pieces of size 2 and 5, and use the existing ribbon of size 5. This gives us 5 ribbons total of size 5.
Algorithm
We use binary search to find the maximum possible ribbon length ?
- Set
left = 0andright = maximum of ribbons - While
left < right:- Calculate
mid = (left + right + 1) // 2 - Count how many ribbons of length
midwe can get - If count ? k, search for larger length:
left = mid - Otherwise, search for smaller length:
right = mid - 1
- Calculate
- Return
leftif non-zero, otherwise-1
Implementation
def solve(ribbons, k):
left = 0
right = max(ribbons)
while left < right:
mid = (left + right + 1) // 2
# Count how many ribbons of length 'mid' we can get
count = sum(ribbon_len // mid for ribbon_len in ribbons)
if count >= k:
left = mid # Try for a larger length
else:
right = mid - 1 # Try for a smaller length
return left if left > 0 else -1
# Test the function
ribbons = [1, 2, 5, 7, 15]
k = 5
result = solve(ribbons, k)
print(f"Maximum ribbon length: {result}")
Maximum ribbon length: 5
How It Works
Let's trace through the example step by step ?
def solve_with_trace(ribbons, k):
left = 0
right = max(ribbons)
print(f"Initial range: [{left}, {right}]")
while left < right:
mid = (left + right + 1) // 2
count = sum(ribbon_len // mid for ribbon_len in ribbons)
print(f"Trying length {mid}: can get {count} ribbons")
if count >= k:
left = mid
print(f" Sufficient! New range: [{left}, {right}]")
else:
right = mid - 1
print(f" Not enough. New range: [{left}, {right}]")
return left if left > 0 else -1
ribbons = [1, 2, 5, 7, 15]
k = 5
result = solve_with_trace(ribbons, k)
print(f"\nFinal answer: {result}")
Initial range: [0, 15] Trying length 8: can get 3 ribbons Not enough. New range: [0, 7] Trying length 4: can get 6 ribbons Sufficient! New range: [4, 7] Trying length 6: can get 4 ribbons Not enough. New range: [4, 5] Trying length 5: can get 5 ribbons Sufficient! New range: [5, 5] Final answer: 5
Edge Cases
# Test edge cases
test_cases = [
([1, 2, 3], 10), # Impossible case
([10, 20, 30], 3), # Each ribbon used once
([5, 5, 5], 3), # All same length
]
for ribbons, k in test_cases:
result = solve(ribbons, k)
print(f"ribbons={ribbons}, k={k} ? {result}")
ribbons=[1, 2, 3], k=10 ? -1 ribbons=[10, 20, 30], k=3 ? 10 ribbons=[5, 5, 5], k=3 ? 5
Conclusion
This solution uses binary search to efficiently find the maximum ribbon length in O(n log(max_length)) time. The key insight is that if we can make k ribbons of length x, we can also make k ribbons of any length smaller than x.
