Partition String Into Minimum Beautiful Substrings
MEDIUMDescription
Given a binary string s, partition the string into one or more substrings such that each substring is beautiful.
A string is beautiful if:
- It doesn't contain leading zeros.
- It's the binary representation of a number that is a power of
5.
Return the minimum number of substrings in such partition. If it is impossible to partition the string s into beautiful substrings, return -1.
A substring is a contiguous sequence of characters in a string.
Example 1:
Input: s = "1011" Output: 2 Explanation: We can paritition the given string into ["101", "1"]. - The string "101" does not contain leading zeros and is the binary representation of integer 51 = 5. - The string "1" does not contain leading zeros and is the binary representation of integer 50 = 1. It can be shown that 2 is the minimum number of beautiful substrings that s can be partitioned into.
Example 2:
Input: s = "111" Output: 3 Explanation: We can paritition the given string into ["1", "1", "1"]. - The string "1" does not contain leading zeros and is the binary representation of integer 50 = 1. It can be shown that 3 is the minimum number of beautiful substrings that s can be partitioned into.
Example 3:
Input: s = "0" Output: -1 Explanation: We can not partition the given string into beautiful substrings.
Constraints:
1 <= s.length <= 15s[i]is either'0'or'1'.
Approaches
Checkout 2 different approaches to solve Partition String Into Minimum Beautiful Substrings. Click on different approaches to view the approach and algorithm in detail.
Dynamic Programming (Memoization / Iterative)
This approach uses dynamic programming to solve the problem efficiently by breaking it down into overlapping subproblems and solving each subproblem only once. We can implement this using either a top-down (memoization) or a bottom-up (iterative) method. Both have the same time complexity and are optimal for this problem.
Algorithm
- The core idea is to define a state
dp[i]representing the minimum number of beautiful partitions for the suffix of the string,s[i..n-1]. - The goal is to find
dp[0]. - Base Case:
dp[n] = 0, as an empty suffix requires 0 partitions. - Recurrence Relation:
dp[i] = min(1 + dp[j+1])over alljfromiton-1such that the substrings[i..j]is beautiful. If no suchjexists,dp[i]is infinity. - This can be implemented in two ways:
- Top-Down (Memoization): Use a recursive function with a memoization table
memoto store results ofdp[i]. Before computing, checkmemo[i]. After computing, store the result inmemo[i]. - Bottom-Up (Iterative): Use an array
dpof sizen+1. Iterateifromn-1down to0. For eachi, calculatedp[i]using the already computed valuesdp[j+1].
- Top-Down (Memoization): Use a recursive function with a memoization table
The brute-force approach is inefficient because it repeatedly solves the same subproblems. We can optimize this by storing the results of subproblems. Let dp[i] be the minimum number of beautiful partitions for the suffix s[i..n-1]. Our goal is to find dp[0].
Top-Down DP (Memoization)
This is a direct optimization of the recursive solution. We use a memoization array (e.g., memo) to store the results of solve(i). Before computing solve(i), we check if the result is already in memo. If so, we return it. Otherwise, we compute it, store it in memo, and then return it. This ensures each state is computed only once.
// Top-Down DP with Memoization
class Solution {
int[] memo;
public int beautifulPartitions(String s) {
int n = s.length();
memo = new int[n + 1];
java.util.Arrays.fill(memo, -1);
int result = solve(s, 0);
return result >= 1_000_000 ? -1 : result;
}
private int solve(String s, int i) {
if (i == s.length()) return 0;
if (memo[i] != -1) return memo[i];
if (s.charAt(i) == '0') return memo[i] = 1_000_000;
int res = 1_000_000;
long val = 0;
for (int j = i; j < s.length(); j++) {
val = val * 2 + (s.charAt(j) - '0');
if (isPowerOfFive(val)) {
res = Math.min(res, 1 + solve(s, j + 1));
}
}
return memo[i] = res;
}
private boolean isPowerOfFive(long n) { /* ... */ }
}
Bottom-Up DP (Iterative)
This approach builds the solution iteratively, eliminating recursion. We create a dp array of size n+1, initialize dp[n] = 0 and the rest to infinity. We loop from i = n-1 down to 0. For each i, we calculate dp[i] using the values of dp[j+1] that have already been computed.
// Bottom-Up Iterative DP
class Solution {
public int beautifulPartitions(String s) {
int n = s.length();
int[] dp = new int[n + 1];
java.util.Arrays.fill(dp, 1_000_000);
dp[n] = 0;
for (int i = n - 1; i >= 0; i--) {
if (s.charAt(i) == '0') continue;
long val = 0;
for (int j = i; j < n; j++) {
val = val * 2 + (s.charAt(j) - '0');
if (isPowerOfFive(val)) {
if (dp[j + 1] < 1_000_000) {
dp[i] = Math.min(dp[i], 1 + dp[j + 1]);
}
}
}
}
return dp[0] >= 1_000_000 ? -1 : dp[0];
}
private boolean isPowerOfFive(long n) { /* ... */ }
}
Complexity Analysis
Pros and Cons
- Highly efficient and optimal for this problem.
- Guarantees that each subproblem is solved only once.
- The iterative version avoids recursion overhead and potential stack overflow issues on larger inputs.
- Requires extra space for the DP table/memoization cache.
- The logic can be slightly more complex to formulate compared to a simple brute-force approach.
Code Solutions
Checking out 3 solutions in different languages for Partition String Into Minimum Beautiful Substrings. Click on different languages to view the code.
class Solution {
private
Integer[] f;
private
String s;
private
Set<Long> ss = new HashSet<>();
private
int n;
public
int minimumBeautifulSubstrings(String s) {
n = s.length();
this.s = s;
f = new Integer[n];
long x = 1;
for (int i = 0; i <= n; ++i) {
ss.add(x);
x *= 5;
}
int ans = dfs(0);
return ans > n ? -1 : ans;
}
private
int dfs(int i) {
if (i >= n) {
return 0;
}
if (s.charAt(i) == '0') {
return n + 1;
}
if (f[i] != null) {
return f[i];
}
long x = 0;
int ans = n + 1;
for (int j = i; j < n; ++j) {
x = x << 1 | (s.charAt(j) - '0');
if (ss.contains(x)) {
ans = Math.min(ans, 1 + dfs(j + 1));
}
}
return f[i] = ans;
}
}
Video Solution
Watch the video walkthrough for Partition String Into Minimum Beautiful Substrings
Similar Questions
5 related questions you might find useful
Patterns:
Data Structures:
Subscribe to Scale Engineer newsletter
Learn about System Design, Software Engineering, and interview experiences every week.
No spam, unsubscribe at any time.