Count of Valid Partitions such that all Partitions lie in Range [1, L]
Last Updated :
04 Dec, 2023
Given a string S containing only digits and an integer L, find the number of ways to partition the given string such that each partition forms a number that lies between the range [1, L]. Since the answer may be very large, return the answer modulo 109+7.
Examples:
Input: S = “1000”, L = 10000
Output: 1
Explanation: The only possible partition is [1000]
Input: S = “1317”, L = 2000
Output: 8
Explanation: Possible partitions are [1317], [131, 7], [13, 17], [1, 317], [13, 1, 7], [1, 31, 7], [1, 3, 17], [1, 3, 1, 7]
Approach: To solve the problem follow the below idea:
The idea is to generate all possible partitions using recursion , if the current partition starts with zero then skip it as no number in the range [1, L] starts with 0, and finally if we found one way of generating different valid partitions from given string then increment the answer by 1. We can further reduce the time complexity using memoization.
Steps to solve the problem:
- Initialize a variable num to keep track of the current partition being formed and ans to keep track of total valid partitions.
- Iterate over the substring starting from the current index i up to the end of the string.
- If the current character at index i is ‘0’, it cannot be a part of any valid partition as no number in range [1, L] starts with 0, so return 0.
- For each digit, update num by appending the digit and check if the number num is less than or equal to the limit L.
- If num is less than or equal to L, make a recursive call to solver with the updated index j+1. This represents the scenario where we continue forming the current number num and move to the next character.
- If num is greater than L, then break the loop.
- If we have reached the end of the string (i == s.size()), return 1. This represents a valid way to split the string.
- Accumulate the results (ans) from all valid recursive calls.
Below is the implementation of the above approach:
C++14
#include <bits/stdc++.h>
using namespace std;
int solver( const string& s, long L, int i, vector< int >& dp)
{
if (i == s.size())
return 1;
if (s[i] == '0' )
return 0;
if (dp[i] != -1)
return dp[i];
int ans = 0;
long num = 0;
for ( int j = i; j < s.size(); j++) {
num = num * 10 + s[j] - '0' ;
if (num > L)
break ;
ans += solver(s, L, j + 1, dp);
ans %= 1000000007;
}
return dp[i] = ans;
}
int NumberOfWays(string s, int L)
{
vector< int > dp(s.size(), -1);
return solver(s, L, 0, dp);
}
int main()
{
string s = "1000";
int L = 10000;
cout << NumberOfWays(s, L);
return 0;
}
|
Java
import java.util.Arrays;
public class Main {
static int solver(String s, long L, int i, int [] dp)
{
if (i == s.length())
return 1 ;
if (s.charAt(i) == '0' )
return 0 ;
if (dp[i] != - 1 )
return dp[i];
int ans = 0 ;
long num = 0 ;
for ( int j = i; j < s.length(); j++) {
num = num * 10 + s.charAt(j) - '0' ;
if (num > L)
break ;
ans += solver(s, L, j + 1 , dp);
ans %= 1000000007 ;
}
dp[i] = ans;
return ans;
}
static int numberOfWays(String s, int L)
{
int [] dp = new int [s.length()];
Arrays.fill(dp, - 1 );
return solver(s, L, 0 , dp);
}
public static void main(String[] args)
{
String s = "1000" ;
int L = 10000 ;
System.out.println(numberOfWays(s, L));
}
}
|
Python3
def solver(s, L, i, dp):
if i = = len (s):
return 1
if s[i] = = '0' :
return 0
if dp[i] ! = - 1 :
return dp[i]
ans = 0
num = 0
for j in range (i, len (s)):
num = num * 10 + int (s[j])
if num > L:
break
ans + = solver(s, L, j + 1 , dp)
ans % = 1000000007
dp[i] = ans
return ans
def NumberOfWays(s, L):
dp = [ - 1 ] * len (s)
return solver(s, L, 0 , dp)
s = "1000"
L = 10000
print (NumberOfWays(s, L))
|
C#
using System;
using System.Collections.Generic;
public class GFG
{
static int Solver( string s, long L, int i, int [] dp)
{
if (i == s.Length)
return 1;
if (s[i] == '0' )
return 0;
if (dp[i] != -1)
return dp[i];
int ans = 0;
long num = 0;
for ( int j = i; j < s.Length; j++)
{
num = num * 10 + (s[j] - '0' );
if (num > L)
break ;
ans += Solver(s, L, j + 1, dp);
ans %= 1000000007;
}
return dp[i] = ans;
}
static int NumberOfWays( string s, int L)
{
int [] dp = new int [s.Length];
Array.Fill(dp, -1);
return Solver(s, L, 0, dp);
}
public static void Main( string [] args)
{
string s = "1000" ;
int L = 10000;
Console.WriteLine(NumberOfWays(s, L));
}
}
|
Javascript
function solver(s, L, i, dp) {
if (i === s.length) {
return 1;
}
if (s[i] === '0' ) {
return 0;
}
if (dp[i] !== -1) {
return dp[i];
}
let ans = 0;
let num = 0;
for (let j = i; j < s.length; j++) {
num = num * 10 + parseInt(s[j]);
if (num > L) {
break ;
}
ans += solver(s, L, j + 1, dp);
ans %= 1000000007;
}
dp[i] = ans;
return ans;
}
function NumberOfWays(s, L) {
let dp = new Array(s.length).fill(-1);
return solver(s, L, 0, dp);
}
function main() {
let s = "1000" ;
let L = 10000;
console.log(NumberOfWays(s, L));
}
main();
|
Time Complexity: O(N2), where N is the length of the input string S.
Auxiliary Space: O(N), which is due to dp[] vector used for memoization.
Share your thoughts in the comments
Please Login to comment...