14. Cutting Binary String

βœ… GFG solution to the Cutting Binary String problem: find minimum cuts to split binary string into substrings representing powers of 5 using dynamic programming. πŸš€

The problem can be found at the following link: πŸ”— Question Link

🧩 Problem Description

You are given a binary string s consisting only of characters '0' and '1'. Your task is to split this string into the minimum number of non-empty substrings such that:

  • Each substring represents a power of 5 in decimal (e.g., 1, 5, 25, 125, ...).

  • No substring should have leading zeros.

Return the minimum number of such pieces the string can be divided into.

Note: If it is not possible to split the string in this way, return -1.

πŸ“˜ Examples

Example 1

Input: s = "101101101"
Output: 3
Explanation: The string can be split into three substrings: "101", "101", and "101",
each of which is a power of 5 with no leading zeros.

Example 2

Input: s = "1111101"
Output: 1
Explanation: The string can be split into one binary string "1111101" which is 125
in decimal and a power of 5 with no leading zeros.

Example 3

πŸ”’ Constraints

  • $1 \le s.size() \le 30$

βœ… My Approach

The optimal approach uses Dynamic Programming with precomputed powers of 5 to efficiently find the minimum cuts:

Dynamic Programming + Hash Set

  1. Early Validation:

    • If the first character is '0', return -1 immediately (no valid split possible).

  2. Precompute Powers of 5:

    • Generate all powers of 5 up to 10^9 (within reasonable limits for 30-bit strings).

    • Store them in a hash set for O(1) lookup.

  3. DP State Definition:

    • dp[i] = minimum cuts needed to split substring from index i to end.

    • Base case: dp[n] = 0 (empty string needs 0 cuts).

  4. DP Transition:

    • For each position i from right to left:

      • Skip if current character is '0' (no valid substring can start with '0').

      • Try all possible substrings starting from i.

      • Convert binary substring to decimal using bit manipulation.

      • If the number is a power of 5, update dp[i] = min(dp[i], 1 + dp[j+1]).

  5. Optimization:

    • Use bitwise operations for faster binary-to-decimal conversion.

    • Break early if the number exceeds 10^9 to avoid overflow.

πŸ“ Time and Auxiliary Space Complexity

  • Expected Time Complexity: O(nΒ²), where n is the length of the string. For each starting position, we check all possible ending positions, and each check involves O(1) operations for power-of-5 validation.

  • Expected Auxiliary Space Complexity: O(log n + n), where log n space is used for storing precomputed powers of 5 (approximately 14 powers for numbers up to 10^9), and O(n) space for the DP array.

πŸ§‘β€πŸ’» Code (C++)

⚑ View Alternative Approaches with Code and Analysis

πŸ“Š 2️⃣ Memoized Recursion with Pruning

πŸ’‘ Algorithm Steps:

  1. Use memoization to avoid recomputation of subproblems.

  2. Early pruning when number exceeds limit to prevent overflow.

  3. Bitwise operations for faster binary-to-decimal conversion.

  4. Direct power-of-5 checking using precomputed hash set.

πŸ“ Complexity Analysis:

  • Time: ⏱️ O(nΒ² log n)

  • Auxiliary Space: πŸ’Ύ O(n) - for memoization table

βœ… Why This Approach?

  • Natural recursive structure makes logic clear.

  • Memoization prevents redundant calculations.

  • Easy to understand and debug step by step.

πŸ“Š 3️⃣ BFS with State Compression

πŸ’‘ Algorithm Steps:

  1. Use BFS to find minimum cuts level by level.

  2. Each state represents current position in string.

  3. Explore all valid power-of-5 substrings from current position.

  4. Level-order traversal ensures we find minimum cuts first.

πŸ“ Complexity Analysis:

  • Time: ⏱️ O(nΒ²)

  • Auxiliary Space: πŸ’Ύ O(n) - for queue and visited array

βœ… Why This Approach?

  • Guarantees finding minimum cuts first.

  • Level-order exploration is intuitive.

  • Natural BFS structure for shortest path problems.

πŸ†š πŸ” Comparison of Approaches

πŸš€ Approach

⏱️ Time Complexity

πŸ’Ύ Space Complexity

βœ… Pros

⚠️ Cons

πŸ” DP with Hash Set

🟒 O(n²)

🟑 O(log n + n)

πŸš€ Optimal for most cases

πŸ’Ύ Hash table overhead

πŸ”Ί Memoized Recursion

🟑 O(n² log n)

🟑 O(n)

πŸ”§ Natural recursive structure

πŸ’Ύ Function call overhead

⏰ BFS Approach

🟒 O(n²)

🟑 O(n)

⚑ Guarantees minimum cuts

πŸ”§ Queue management overhead

πŸ† Best Choice Recommendation

🎯 Scenario

πŸŽ–οΈ Recommended Approach

πŸ”₯ Performance Rating

⚑ General purpose, balanced performance

πŸ₯‡ DP with Hash Set

β˜…β˜…β˜…β˜…β˜…

🎯 Recursive thinking preference

πŸ₯ˆ Memoized Recursion

β˜…β˜…β˜…β˜…β˜†

πŸš€ Shortest path guarantee needed

πŸ₯‰ BFS Approach

β˜…β˜…β˜…β˜†β˜†

πŸ§‘β€πŸ’» Code (Java)

🐍 Code (Python)

🧠 Contribution and Support

For discussions, questions, or doubts related to this solution, feel free to connect on LinkedIn: πŸ“¬ Any Questions?. Let's make this learning journey more collaborative!

⭐ If you find this helpful, please give this repository a star! ⭐


πŸ“Visitor Count

Visitor counter

Last updated