Minimum Partition of Binary String into Powers of 5
Last Updated :
08 Jul, 2025
Given a binary string s, divide it into the fewest number of substrings such that:
- Each substring represents a power of 5 in binary format.
- No substring has leading zeros.
- Each substring must represent a positive power of 5 (e.g., 1, 5, 25, 125, ...).
Return the minimum number of such substrings. If no valid division exists, return -1.
Examples:
Input: str = "101101101"
Output: 3
Explanation: The string "101101101" can be cut into three binary strings "101", "101", "101" each of which is a power of 5.
Input: str = "1111101"
Output: 1
Explanation: The string "1111101" can be cut into one binary string "1111101" which is 125 in decimal and a power of 5.
Input: str = "00000"
Output: -1
Explanation: Strings of only zeroes is equivalent to 0 which is not a power of 5.
[Naive approach] Recursive String Splitting
The idea is to recursively split the binary string into substrings that represent powers of 5 without leading zeros. At each index, we try all possible substrings starting from that position. If a substring is valid, we recursively solve for the remaining part of the string. We return the minimum number of such valid splits needed to partition the entire string.
C++
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
// function to check if a number is a power of 5
bool check(int num) {
if (num == 0) return false;
while (num % 5 == 0) {
num /= 5;
}
return num == 1;
}
// recursive function to compute minimum cuts
int findMinCuts(int i, string &s) {
int n = s.size();
if (i >= n) return 0;
int ans = n+1;
int num = 0;
for (int j = i; j < n; j++) {
num = num * 2 + (s[j] == '1');
// ensure there is no leading '0'
// and the number is a power of 5
if (s[i] != '0' && check(num)) {
int next = findMinCuts(j + 1, s);
if (next != n+1) {
ans = min(ans, 1 + next);
}
}
}
return ans;
}
int cuts(string &s) {
if (s[0] == '0') return -1;
int n = s.size();
int ans = findMinCuts(0, s);
if (ans >= n+1) return -1;
return ans;
}
int main() {
string s = "101101101";
int res = cuts(s);
cout << res << endl;
return 0;
}
Java
class GfG {
// function to check if a number is a power of 5
static boolean check(int num) {
if (num == 0) return false;
while (num % 5 == 0) {
num /= 5;
}
return num == 1;
}
// recursive function to compute minimum cuts
static int findMinCuts(int i, String s) {
int n = s.length();
if (i >= n) return 0;
int ans = n+1;
int num = 0;
for (int j = i; j < n; j++) {
num = num * 2 + (s.charAt(j) == '1' ? 1 : 0);
// ensure there is no leading '0'
// and the number is a power of 5
if (s.charAt(i) != '0' && check(num)) {
int next = findMinCuts(j + 1, s);
if (next != n+1) {
ans = Math.min(ans, 1 + next);
}
}
}
return ans;
}
static int cuts(String s) {
if (s.charAt(0) == '0') return -1;
int n = s.length();
int ans = findMinCuts(0, s);
if (ans >= n+1) return -1;
return ans;
}
public static void main(String[] args) {
String s = "101101101";
int res = cuts(s);
System.out.println(res);
}
}
Python
# function to check if a number is a power of 5
def check(num):
if num == 0:
return False
while num % 5 == 0:
num //= 5
return num == 1
# recursive function to compute minimum cuts
def findMinCuts(i, s):
n = len(s)
if i >= n:
return 0
ans = n+1
num = 0
for j in range(i, n):
num = num * 2 + (1 if s[j] == '1' else 0)
# ensure there is no leading '0'
# and the number is a power of 5
if s[i] != '0' and check(num):
next_cuts = findMinCuts(j + 1, s)
if next_cuts != n+1:
ans = min(ans, 1 + next_cuts)
return ans
def cuts(s):
if s[0] == '0':
return -1
n = len(s)
ans = findMinCuts(0, s)
if ans >= n+1:
return -1
return ans
if __name__ == "__main__":
s = "101101101"
res = cuts(s)
print(res)
C#
using System;
class GfG {
// function to check if a number is a power of 5
static bool check(int num) {
if (num == 0) return false;
while (num % 5 == 0) {
num /= 5;
}
return num == 1;
}
// recursive function to compute minimum cuts
static int findMinCuts(int i, string s) {
int n = s.Length;
if (i >= n) return 0;
int ans = n+1;
int num = 0;
for (int j = i; j < n; j++) {
num = num * 2 + (s[j] == '1' ? 1 : 0);
// ensure there is no leading '0'
// and the number is a power of 5
if (s[i] != '0' && check(num)) {
int next = findMinCuts(j + 1, s);
if (next != n+1) {
ans = Math.Min(ans, 1 + next);
}
}
}
return ans;
}
static int cuts(string s) {
if (s[0] == '0') return -1;
int n = s.Length;
int ans = findMinCuts(0, s);
if (ans >= n+1) return -1;
return ans;
}
static void Main(string[] args) {
string s = "101101101";
int res = cuts(s);
Console.WriteLine(res);
}
}
JavaScript
// function to check if a number is a power of 5
function check(num) {
if (num === 0) return false;
while (num % 5 === 0) {
num = Math.floor(num / 5);
}
return num === 1;
}
// recursive function to compute minimum cuts
function findMinCuts(i, s) {
const n = s.length;
if (i >= n) return 0;
let ans = n+1;
let num = 0;
for (let j = i; j < n; j++) {
num = num * 2 + (s[j] === '1' ? 1 : 0);
// ensure there is no leading '0'
// and the number is a power of 5
if (s[i] !== '0' && check(num)) {
let next = findMinCuts(j + 1, s);
if (next !== n+1) {
ans = Math.min(ans, 1 + next);
}
}
}
return ans;
}
function cuts(s) {
if (s[0] === '0') return -1;
const n = s.length;
let ans = findMinCuts(0, s);
if (ans >= n+1) return -1;
return ans;
}
// Driver Code
let s = "101101101";
let res = cuts(s);
console.log(res);
Time Complexity: O(2n) we try all possible partitions starting from each index, leading to an exponential number of recursive calls.
Auxiliary Space: O(n) the recursion stack can go as deep as the length of the string.
[Expected approach] Recursive String Splitting with Memoization and Precomputation
The idea is to recursively split the binary string into valid substrings that represent powers of 5 and have no leading zeros.
We define the state as memo[i] — the minimum number of cuts needed to partition the substring starting from index i.
At each index i, we try every substring s[i..j] and if it’s valid, we update: memo[i] = min(memo[i], 1 + memo[j + 1]). We use memoization (memo[] array) to store results and avoid recomputing overlapping subproblems. All valid powers of 5 are precomputed for constant-time lookup during substring validation.
C++
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <unordered_set>
using namespace std;
// recursive function to compute minimum
// cuts with memoization
int findMinCuts(int i, string &s, vector<int> &memo,
unordered_set<int> &powersOf5) {
int n = s.size();
if (i >= n) return 0;
if (memo[i] != -1) return memo[i];
int ans = n+1;
int num = 0;
for (int j = i; j < n; j++) {
num = num * 2 + (s[j] == '1');
// ensure there is no leading '0'
// and the number is a power of 5
if (s[i] != '0' && powersOf5.count(num)) {
int next = findMinCuts(j + 1, s, memo, powersOf5);
if (next != n+1) {
ans = min(ans, 1 + next);
}
}
}
return memo[i] = ans;
}
int cuts(string &s) {
if (s[0] == '0') return -1;
// store power of 5
unordered_set<int> powersOf5;
int val = 1;
while (val <= 1e9) {
powersOf5.insert(val);
val *= 5;
}
int n = s.size();
vector<int> memo(n + 1, -1);
int ans = findMinCuts(0, s, memo, powersOf5);
if (ans >= n+1) return -1;
return ans;
}
int main() {
string s = "101101101";
int res = cuts(s);
cout << res << endl;
return 0;
}
Java
import java.util.Set;
import java.util.HashSet;
import java.util.Arrays;
class GfG {
// recursive function to compute minimum cuts with memoization
static int findMinCuts(int i, String s, int[] memo,
Set<Integer> powersOf5) {
int n = s.length();
if (i >= n) return 0;
if (memo[i] != -1) return memo[i];
int ans = n + 1;
int num = 0;
for (int j = i; j < n; j++) {
num = num * 2 + (s.charAt(j) == '1' ? 1 : 0);
// ensure there is no leading '0'
// and the number is a power of 5
if (s.charAt(i) != '0' && powersOf5.contains(num)) {
int next = findMinCuts(j + 1, s, memo, powersOf5);
if (next != n + 1) {
ans = Math.min(ans, 1 + next);
}
}
}
return memo[i] = ans;
}
static int cuts(String s) {
if (s.charAt(0) == '0') return -1;
// store power of 5
Set<Integer> powersOf5 = new HashSet<>();
int val = 1;
while (val <= 1_000_000_000) {
powersOf5.add(val);
val *= 5;
}
int n = s.length();
int[] memo = new int[n + 1];
Arrays.fill(memo, -1);
int ans = findMinCuts(0, s, memo, powersOf5);
return (ans >= n + 1) ? -1 : ans;
}
public static void main(String[] args) {
String s = "101101101";
int res = cuts(s);
System.out.println(res);
}
}
Python
# recursive function to compute minimum cuts with memoization
def findMinCuts(i, s, memo, powersOf5):
n = len(s)
if i >= n:
return 0
if memo[i] != -1:
return memo[i]
ans = n+1
num = 0
for j in range(i, n):
num = num * 2 + (1 if s[j] == '1' else 0)
# ensure there is no leading '0'
# and the number is a power of 5
if s[i] != '0' and num in powersOf5:
next_cut = findMinCuts(j + 1, s, memo, powersOf5)
if next_cut != n+1:
ans = min(ans, 1 + next_cut)
memo[i] = ans
return ans
def cuts(s):
if s[0] == '0':
return -1
# store power of 5
powersOf5 = set()
val = 1
while val <= 10**9:
powersOf5.add(val)
val *= 5
n = len(s)
memo = [-1] * (n + 1)
ans = findMinCuts(0, s, memo, powersOf5)
return -1 if ans >= n+1 else ans
if __name__ == "__main__":
s = "101101101"
res = cuts(s)
print(res)
C#
using System;
using System.Collections.Generic;
class GfG {
// recursive function to compute minimum
// cuts with memoization
static int findMinCuts(int i, string s, int[] memo,
HashSet<int> powersOf5) {
int n = s.Length;
if (i >= n) return 0;
if (memo[i] != -1) return memo[i];
int ans = n+1;
int num = 0;
for (int j = i; j < n; j++) {
num = num * 2 + (s[j] == '1' ? 1 : 0);
// ensure there is no leading '0'
// and the number is a power of 5
if (s[i] != '0' && powersOf5.Contains(num)) {
int next = findMinCuts(j + 1, s, memo, powersOf5);
if (next != n+1) {
ans = Math.Min(ans, 1 + next);
}
}
}
return memo[i] = ans;
}
static int cuts(string s) {
if (s[0] == '0') return -1;
// store power of 5
HashSet<int> powersOf5 = new HashSet<int>();
int val = 1;
while (val <= 1000000000) {
powersOf5.Add(val);
val *= 5;
}
int n = s.Length;
int[] memo = new int[n + 1];
Array.Fill(memo, -1);
int ans = findMinCuts(0, s, memo, powersOf5);
return (ans >= n+1) ? -1 : ans;
}
static void Main(string[] args) {
string s = "101101101";
int res = cuts(s);
Console.WriteLine(res);
}
}
JavaScript
// recursive function to compute minimum
// cuts with memoization
function findMinCuts(i, s, memo, powersOf5) {
const n = s.length;
if (i >= n) return 0;
if (memo[i] !== -1) return memo[i];
let ans = n+1;
let num = 0;
for (let j = i; j < n; j++) {
num = num * 2 + (s[j] === '1' ? 1 : 0);
// ensure there is no leading '0'
// and the number is a power of 5
if (s[i] !== '0' && powersOf5.has(num)) {
const next = findMinCuts(j + 1, s, memo, powersOf5);
if (next !== n+1) {
ans = Math.min(ans, 1 + next);
}
}
}
memo[i] = ans;
return ans;
}
function cuts(s) {
if (s[0] === '0') return -1;
// store power of 5
const powersOf5 = new Set();
let val = 1;
while (val <= 1e9) {
powersOf5.add(val);
val *= 5;
}
const n = s.length;
const memo = new Array(n + 1).fill(-1);
const ans = findMinCuts(0, s, memo, powersOf5);
return ans >= n+1 ? -1 : ans;
}
// Driver Code
const s = "101101101";
const res = cuts(s);
console.log(res);
Time Complexity: O(n²) for each of the n starting indices, we try up to n substrings. Each substring is validated in constant time due to the precomputed powerOf5 set.
Auxiliary Space: O(n) we use a memo array of size n for memoization. The precomputed powers of 5 set uses constant space (O(1)) .
[Efficient approach] Bottom-Up Dynamic Programming with Precomputed Valid Substrings
The idea is to use bottom-up dynamic programming (tabulation) to find the minimum number of cuts to partition a binary string into valid substrings.
A substring is valid if it represents a power of 5 in binary and has no leading zeros.
We iterate from right to left and build up the solution using previously computed results.
State: dp[i] represent the minimum number of cuts needed to partition the suffix s[i..n-1] into valid power of 5 binary substrings.
Transition: At each position i, we try every substring s[i..j] where:
- s[i] != '0' (to avoid leading zeros)
- s[i..j] is a valid binary representation of a power of 5 (checked via precomputed set)
- if both conditions hold: dp[i] = min(dp[i], 1 + dp[j+1])
C++
#include <iostream>
#include <string>
#include <vector>
#include <unordered_set>
#include <algorithm>
using namespace std;
int cuts(string &s) {
if (s[0] == '0') return -1;
int n = s.size();
const int maxi = n+1;
unordered_set<int> powersOf5;
// store power of 5
int val = 1;
while (val <= 1e9) {
powersOf5.insert(val);
val *= 5;
}
vector<int> dp(n + 1, maxi);
// base case empty suffix requires 0 cuts
dp[n] = 0;
for (int i = n - 1; i >= 0; --i) {
// ensure there is no leading '0'
if(s[i] == '0') continue;
int num = 0;
for (int j = i; j < n; ++j) {
num = num * 2 + (s[j] == '1');
// and the number is a power of 5
if (powersOf5.count(num)) {
if (dp[j + 1] != maxi) {
dp[i] = min(dp[i], 1 + dp[j + 1]);
}
}
}
}
return dp[0] >= maxi ? -1 : dp[0];
}
int main() {
string s = "101101101";
int res = cuts(s);
cout << res << endl;
return 0;
}
Java
import java.util.Set;
import java.util.HashSet;
import java.util.Arrays;
class GfG {
public static int cuts(String s) {
if (s.charAt(0) == '0') return -1;
int n = s.length();
int maxi = n+1;
Set<Integer> powersOf5 = new HashSet<>();
// store power of 5
int val = 1;
while (val <= 1_000_000_000) {
powersOf5.add(val);
val *= 5;
}
int[] dp = new int[n + 1];
Arrays.fill(dp, maxi);
// base case empty suffix requires 0 cuts
dp[n] = 0;
for (int i = n - 1; i >= 0; --i) {
// ensure there is no leading '0'
if (s.charAt(i) == '0') continue;
int num = 0;
for (int j = i; j < n; ++j) {
num = num * 2 + (s.charAt(j) == '1' ? 1 : 0);
// and the number is a power of 5
if (powersOf5.contains(num)) {
if (dp[j + 1] != maxi) {
dp[i] = Math.min(dp[i], 1 + dp[j + 1]);
}
}
}
}
return dp[0] >= maxi ? -1 : dp[0];
}
public static void main(String[] args) {
String s = "101101101";
int res = cuts(s);
System.out.println(res);
}
}
Python
def cuts(s):
if s[0] == '0':
return -1
n = len(s)
maxi = n+1
powersOf5 = set()
# store power of 5
val = 1
while val <= 1e9:
powersOf5.add(val)
val *= 5
dp = [maxi] * (n + 1)
# base case empty suffix requires 0 cuts
dp[n] = 0
for i in range(n - 1, -1, -1):
# ensure there is no leading '0'
if s[i] == '0':
continue
num = 0
for j in range(i, n):
num = num * 2 + (1 if s[j] == '1' else 0)
# and the number is a power of 5
if num in powersOf5:
if dp[j + 1] != maxi:
dp[i] = min(dp[i], 1 + dp[j + 1])
return -1 if dp[0] >= maxi else dp[0]
if __name__ == "__main__":
s = "101101101"
res = cuts(s)
print(res)
C#
using System;
using System.Collections.Generic;
class GfG {
public static int cuts(string s) {
if (s[0] == '0') return -1;
int n = s.Length;
int maxi = n+1;
HashSet<int> powersOf5 = new HashSet<int>();
// store power of 5
int val = 1;
while (val <= 1000000000) {
powersOf5.Add(val);
val *= 5;
}
int[] dp = new int[n + 1];
Array.Fill(dp, maxi);
// base case empty suffix requires 0 cuts
dp[n] = 0;
for (int i = n - 1; i >= 0; --i) {
// ensure there is no leading '0'
if (s[i] == '0') continue;
int num = 0;
for (int j = i; j < n; ++j) {
num = num * 2 + (s[j] == '1' ? 1 : 0);
// and the number is a power of 5
if (powersOf5.Contains(num)) {
if (dp[j + 1] != maxi) {
dp[i] = Math.Min(dp[i], 1 + dp[j + 1]);
}
}
}
}
return dp[0] >= maxi ? -1 : dp[0];
}
static void Main(string[] args) {
string s = "101101101";
int res = cuts(s);
Console.WriteLine(res);
}
}
JavaScript
function cuts(s) {
if (s[0] === '0') return -1;
const n = s.length;
const maxi = n+1;
const powersOf5 = new Set();
// store power of 5
let val = 1;
while (val <= 1e9) {
powersOf5.add(val);
val *= 5;
}
const dp = new Array(n + 1).fill(maxi);
// base case empty suffix requires 0 cuts
dp[n] = 0;
for (let i = n - 1; i >= 0; i--) {
// ensure there is no leading '0'
if (s[i] === '0') continue;
let num = 0;
for (let j = i; j < n; j++) {
num = num * 2 + (s[j] === '1' ? 1 : 0);
// and the number is a power of 5
if (powersOf5.has(num)) {
if (dp[j + 1] !== maxi) {
dp[i] = Math.min(dp[i], 1 + dp[j + 1]);
}
}
}
}
return dp[0] >= maxi ? -1 : dp[0];
}
// Driver Code
const s = "101101101";
const res = cuts(s);
console.log(res);
Time Complexity: O(n²) for each index i from n-1 to 0, we try every substring s[i..j] (at most n substrings). Each substring is checked in constant time using a precomputed set of powers of 5.
Auxiliary space: O(n) an array dp[] of size n+1 is used to store minimum cuts. The powewOf5 set uses O(1) space.
Similar Reads
Minimum number of operations required to obtain a given Binary String Given a binary strings S of length N, the task is to obtain S from a string, say T, of length N consisting only of zeroes, by minimum number of operations. Each operation involves choosing any index i from string S and flipping all the bits at indices [i, N - 1] of the string T. Examples: Input: S =
8 min read
Minimum operations require to balance Binary String Given a binary string S of length N, the task is to find the minimum number of operations required to balance (equal number of '0' and '1') the given binary string, you can perform two types of operations one at a time, which is given below. Remove a character from the front of the given string.Remo
7 min read
Minimum operations to convert given string into all 1s or 0s Given a string S containing 0s and 1s of length N with X, the task is to output the minimum operations required to convert S into either all 1s or 0s. The operation is defined as, taking two different indices i and j (1-based indexing), such that they give equal remainder when dividing from X, then
8 min read
Minimum number of Binary strings to represent a Number Given a number N. The task is to find the minimum number of binary strings required to represent the given number as the sum of the binary strings.Examples: Input : 131 Output : Minimum Number of binary strings needed: 3 111 10 10 Input : 564 Output :Minimum Number of binary strings needed: 6 111 11
7 min read
Minimum operations required to convert a binary string to all 0s or all 1s Given a binary string str, the task is to find the minimum number of operations required to make all the characters of the string same i.e. either the resultant string contains all 0s or all 1s. In a single operation, any block of consecutive 0s can be converted to a block of consecutive 1s of the s
4 min read
Number of unique permutations starting with 1 of a Binary String Given a binary string composed of 0's and 1's. The task is to find the number of unique permutation of the string which starts with 1. Note: Since the answer can be very large, print the answer under modulo 109 + 7.Examples: Input : str ="10101001001" Output : 210 Input : str ="101110011" Output : 5
10 min read