Cutting Ribbons

Updated on 16 May, 2025
Cutting Ribbons header image

Problem Statement

In this challenge, you're provided with an array of integers ribbons, where each entry ribbons[i] signifies the length of the ith ribbon, along with an integer k, representing the number you must obtain of such ribbons. The operation allowed on the ribbons is the cutting of any of these into segments of strictly positive integer lengths, or you can also opt not to cut them at all.

The objective boils down to this: find the maximum possible length x for which you can cut or keep ribbons such that you end up with at least k ribbons, all exactly x long. Any sections of ribbon left over after the cuts can be discarded. However, if it’s not feasible to get at least k such equal-length ribbons, the function should return 0.

Examples

Example 1

Input:

ribbons = [9,7,5], k = 3

Output:

5

Explanation:

- Cut the first ribbon to two ribbons, one of length 5 and one of length 4.
- Cut the second ribbon to two ribbons, one of length 5 and one of length 2.
- Keep the third ribbon as it is.
Now you have 3 ribbons of length 5.

Example 2

Input:

ribbons = [7,5,9], k = 4

Output:

4

Explanation:

- Cut the first ribbon to two ribbons, one of length 4 and one of length 3.
- Cut the second ribbon to two ribbons, one of length 4 and one of length 1.
- Cut the third ribbon to three ribbons, two of length 4 and one of length 1.
Now you have 4 ribbons of length 4.

Example 3

Input:

ribbons = [5,7,9], k = 22

Output:

0

Explanation:

You cannot obtain k ribbons of the same positive integer length.

Constraints

  • 1 <= ribbons.length <= 105
  • 1 <= ribbons[i] <= 105
  • 1 <= k <= 109

Approach and Intuition

Based on the examples provided and the constraints, here's an intuitive approach to solving the problem:

  1. Determining Feasibility:

    • If you want k ribbons of length x, then the essential point to check is if it is theoretically possible given the lengths in the ribbons array. If the total length of all ribbons divided by x is less than k, then such x cannot be the answer.
  2. Binary Search for Efficiency:

    • Given the constraint sizes, a direct approach might not be efficient. Instead, using a binary search can help optimize the search for the maximum length x. This is feasible here as if a certain length x can allow cutting at least k ribbons, then any length lesser than x will also do, making the relationship monotonic and suitable for binary search.
  3. Calculate Ribbons in Range:

    • For each mid-point in the binary search, calculate how many total ribbons of that specific length can be obtained from the ribbons array. If it meets or exceeds k, adjust the binary search bounds to explore potentially larger valid lengths.

Through this methodical slicing and exploring using binary search, we can efficiently determine the maximum ribbon length that meets the criteria without manually testing every possible length, respecting the high upper limits of constraints provided.

Solutions

  • C++
  • Java
  • Python
cpp
class Solution {
public:
    int findMaxLength(vector<int>& ribbons, int k) {
        int minLen = 0;
        int maxLen = *max_element(ribbons.begin(), ribbons.end());

        while (minLen < maxLen) {
            int mid = (minLen + maxLen + 1) / 2;
            if (canCutRibbons(mid, ribbons, k)) {
                minLen = mid;
            } else {
                maxLen = mid - 1;
            }
        }
        return minLen;
    }

private:
    bool canCutRibbons(int length, vector<int>& ribbons, int k) {
        int count = 0;
        for (int ribbon : ribbons) {
            count += ribbon / length;
            if (count >= k) return true;
        }
        return false;
    }
};

The provided C++ code is designed to solve the problem of cutting ribbons into parts of equal length. The main objective is to find the maximum length of each part such that at least k parts can be obtained from the given ribbons. The solution implements a binary search technique to efficiently determine this maximum length.

  • Initialize two pointers:

    • minLen to 0, representing the minimum possible length of a ribbon part.
    • maxLen to the length of the longest ribbon, determined using max_element.
  • Perform binary search:

    • Calculate the middle value mid as the average of minLen and maxLen plus one.
    • Use the helper function canCutRibbons to check if it's possible to cut the ribbons into at least k parts of length mid.
    • If true, adjust minLen to mid to try a potentially longer length.
    • If false, adjust maxLen to mid - 1 to try a shorter length.
  • The function canCutRibbons checks feasibility:

    • Iterate through each ribbon, adding to a count the number of pieces of length mid that can be cut from the ribbon.
    • If the accumulated count meets or exceeds k during iteration, return true.
  • The loop continues until minLen is less than maxLen. After exiting the loop, minLen is returned as it represents the maximum length that allows cutting at least k parts.

This method efficiently finds the solution by narrowing down the search space using binary search principles and performing linear checks within the helper function.

java
class Solution {

    public int maxRibbonLength(int[] ribbons, int requiredPieces) {
        int low = 0;
        int high = Arrays.stream(ribbons).max().getAsInt();

        while (low < high) {
            int mid = (low + high + 1) / 2;
            if (canCutRibbonsToSize(mid, ribbons, requiredPieces)) {
                low = mid;
            } else {
                high = mid - 1;
            }
        }
        return low;
    }

    private boolean canCutRibbonsToSize(int length, int[] ribbons, int neededPieces) {
        int count = 0;
        for (int ribbon : ribbons) {
            count += ribbon / length;
            if (count >= neededPieces) return true;
        }
        return false;
    }
}

In the "Cutting Ribbons" problem, the objective is to determine the maximum size of ribbon lengths that can be cut a specified number of times from an array of ribbon lengths. The solution involves implementing a binary search to efficiently find the maximum ribbon length that allows cutting at least the required number of pieces.

Here's how the solution works:

  1. Initialize two variables, low and high. low starts at 0, and high is set to the maximum value in the ribbon array.
  2. Execute a binary search by calculating the midpoint (mid) between low and high.
  3. For each midpoint, check if it's possible to cut the ribbons into the required number of pieces of length mid. This is done using the canCutRibbonsToSize helper method.
  4. If you can cut the required pieces, adjust low to mid, indicating the need to search for a possibly longer viable length.
  5. If not, adjust high to mid - 1 to search for shorter lengths.
  6. The loop continues until low is less than high. At this point, low will hold the value of the longest possible length to cut the required number of pieces.

The helper method canCutRibbonsToSize performs the following:

  • It calculates the total number of pieces you can cut from each ribbon at a specified length.
  • If the total meets or exceeds the required number of pieces, the method returns true.
  • If not, it continues checking with the remaining ribbons.

By implementing this approach:

  • Employ a binary search to leverage efficiency in narrowing down the possible maximum length.
  • Use a greedy strategy within the helper method to count the pieces achievable per ribbon length, ensuring the method is both effective and efficient.

This method is particularly efficient, operating in a logarithmic time complexity in relation to the range of ribbon lengths, due to the binary search, and linear in relation to the number of ribbons due to the piece counting loop.

python
class Solution:
    def largestMinLength(self, ribbons: list[int], count: int) -> int:
        min_len = 0
        max_len = max(ribbons)

        while min_len < max_len:
            mid = (min_len + max_len + 1) // 2
            if self._canCut(ribbons, mid, count):
                min_len = mid
            else:
                max_len = mid - 1

        return min_len

    def _canCut(self, length: int, ribbons: list[int], required_count: int) -> bool:
        pieces = 0
        for ribbon in ribbons:
            pieces += ribbon // length
            if pieces >= required_count:
                return True
        return False

In the "Cutting Ribbons" problem, you need to determine the maximum possible minimum length of ribbons when cut from a list of ribbon lengths, such that at least a specified number of equal-length ribbons can be obtained. This solution solves the problem efficiently using a binary search approach in Python.

  • The largestMinLength function initializes min_len to 0 and max_len to the maximum value in the ribbons list.
  • A binary search is performed between min_len and max_len. For each midpoint mid, the function checks if it's possible to cut the required number of pieces of at least mid length using all the given ribbons.
  • The helper method _canCut calculates the total number of pieces of a given length that can be cut from each ribbon in the list. If the sum of all pieces meets or exceeds the required count, it returns True.
  • Adjust min_len and max_len based on whether the required number of pieces can be obtained. If they can, it implies that it might be possible to achieve the same or better with a larger minimum length, so min_len is set to mid. Otherwise, adjust max_len to mid - 1.
  • The min_len variable, adjusted through the binary search, eventually holds the value of the largest minimum ribbon length that allows cutting the required number of pieces.

The binary search technique ensures that the solution is efficient even for large input sizes.

Comments

No comments yet.