Count of non-decreasing numeric string formed by replacing wild card ‘?’
Given a string S of size N consisting of digits and ?, the task is to find the number of strings formed such that replacing the character ‘?’ with any digits such that the digits of the string become non-decreasing.
Examples:
Input: S = “1???2”
Output: 4
Explanation:
The string after valid replacements of ‘?’ is 11112, 11122, 11222, 12222. Therefore, the count of such string is 1.
Input: S = “2??43?4”
Output: 0
Approach: The given problem can be solved by replacing ‘?’ with all possible valid combinations of digits using recursion and store the Overlapping Subproblems in the dp[] table. Follow the steps below to solve the given problem:
- Initialize a 2D array, say dp[][] such that dp[i][j] will denote the possible number of valid strings having the length i and between two numbers whose endpoint difference is j. As the different segments containing ? are independent of each other. So the total count will be the product of all the choices available for each segment.
- Initialize the dp[][] as -1.
- Declare three variables L as 0, R as 9, cnt, such that L denotes the left limit of the segment, R denotes the right limit of the segment, and cnt denotes the length of contiguous ‘?’ characters.
- Let the total count be stored in the variable, say ans as 1.
- Define a function solve that will calculate the values of dp nodes recursively. The solve function will take two arguments (len, gap), len will denote the total length of continuous ‘?’ and the gap will denote the difference between endpoints of that segment as:
- Iterate for each possible gap and recalculate the answer with solve(len – 1, gap – i).
- Return the answer obtained from solve function after filling the node dp[len][gap].
- Iterate through each character in the string and perform the following steps:
- If the current character is ‘?’ then increments the variable cnt.
- If the current character is not a number change the Right limit i.e., R to the current character, i.e., R = S[i] – ‘0’.
- Multiply the answer calculated by the recursive function solve(cnt, R – L).
- After completing the above steps, print the value of ans as the resultant count of strings formed.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
#define MAXN 100005
int dp[MAXN][10];
int solve( int len, int gap)
{
if (dp[len][gap] != -1) {
return dp[len][gap];
}
if (len == 0 || gap == 0) {
return 1;
}
if (gap < 0) {
return 0;
}
int ans = 0;
for ( int i = 0; i <= gap; i++) {
ans += solve(len - 1, gap - i);
}
return dp[len][gap] = ans;
}
int countValidStrings(string S)
{
memset (dp, -1, sizeof (dp));
int N = S.length();
int L = 1, R = 9;
int cnt = 0;
int ans = 1;
for ( int i = 0; i < N; i++) {
if (S[i] != '?' ) {
R = S[i] - '0' ;
ans *= solve(cnt, R - L);
L = R;
R = 9;
cnt = 0;
}
else {
cnt++;
}
}
ans *= solve(cnt, R - L);
return ans;
}
int main()
{
string S = "1???2" ;
cout << countValidStrings(S);
return 0;
}
|
Java
import java.io.*;
class GFG {
static final int MAXN = 100005 ;
static final int dp[][] = new int [MAXN][ 10 ];
static int solve( int len, int gap)
{
if (dp[len][gap] != - 1 ) {
return dp[len][gap];
}
if (len == 0 || gap == 0 ) {
return 1 ;
}
if (gap < 0 ) {
return 0 ;
}
int ans = 0 ;
for ( int i = 0 ; i <= gap; i++) {
ans += solve(len - 1 , gap - i);
}
return dp[len][gap] = ans;
}
static int countValidStrings(String S)
{
for ( int i = 0 ; i < MAXN; i++) {
for ( int j = 0 ; j < 10 ; j++) {
dp[i][j] = - 1 ;
}
}
int N = S.length();
int L = 1 , R = 9 ;
int cnt = 0 ;
int ans = 1 ;
for ( int i = 0 ; i < N; i++) {
if (S.charAt(i) != '?' ) {
R = S.charAt(i) - '0' ;
ans *= solve(cnt, R - L);
L = R;
R = 9 ;
cnt = 0 ;
}
else {
cnt++;
}
}
ans *= solve(cnt, R - L);
return ans;
}
public static void main(String[] args)
{
String S = "1???2" ;
System.out.println(countValidStrings(S));
}
}
|
Python3
MAXN = 100005
dp = [[ - 1 for x in range ( 10 )] for y in range (MAXN)]
def solve( len , gap):
if (dp[ len ][gap] ! = - 1 ):
return dp[ len ][gap]
if ( len = = 0 or gap = = 0 ):
return 1
if (gap < 0 ):
return 0
ans = 0
for i in range (gap + 1 ):
ans + = solve( len - 1 , gap - i)
dp[ len ][gap] = ans
return dp[ len ][gap]
def countValidStrings(S):
global dp
N = len (S)
L, R = 1 , 9
cnt = 0
ans = 1
for i in range (N):
if (S[i] ! = '?' ):
R = ord (S[i]) - ord ( '0' )
ans * = solve(cnt, R - L)
L = R
R = 9
cnt = 0
else :
cnt + = 1
ans * = solve(cnt, R - L)
return ans
if __name__ = = "__main__" :
S = "1???2"
print (countValidStrings(S))
|
C#
using System;
using System.Collections.Generic;
class GFG
{
static int MAXN = 100005;
static int [,]dp = new int [MAXN, 10];
static int solve( int len, int gap)
{
if (dp[len,gap] != -1) {
return dp[len,gap];
}
if (len == 0 || gap == 0) {
return 1;
}
if (gap < 0) {
return 0;
}
int ans = 0;
for ( int i = 0; i <= gap; i++) {
ans += solve(len - 1, gap - i);
}
return dp[len,gap] = ans;
}
static int countValidStrings( string S)
{
for ( int i = 0; i < MAXN; i++){
for ( int j = 0; j < 10; j++){
dp[i, j] = -1;
}
}
int N = S.Length;
int L = 1, R = 9;
int cnt = 0;
int ans = 1;
for ( int i = 0; i < N; i++) {
if (S[i] != '?' ) {
R = ( int )S[i] - 48;
ans *= solve(cnt, R - L);
L = R;
R = 9;
cnt = 0;
}
else {
cnt++;
}
}
ans *= solve(cnt, R - L);
return ans;
}
public static void Main()
{
string S = "1???2" ;
Console.Write(countValidStrings(S));
}
}
|
Javascript
<script>
let MAXN = 100005
let dp = new Array(MAXN).fill( new Array(10));
function solve(len, gap)
{
if (dp[len][gap] != -1) {
return dp[len][gap];
}
if (len == 0 || gap == 0) {
return 1;
}
if (gap < 0) {
return 0;
}
let ans = 0;
for (let i = 0; i <= gap; i++) {
ans += solve(len - 1, gap - i);
}
return dp[len][gap] = ans;
}
function countValidStrings(S)
{
for (let i = 0; i < dp.length; i++) {
for (let j = 0; j < dp[i].length; j++) {
dp[i][j] = -1;
}
}
let N = S.length;
let L = 1, R = 9;
let cnt = 0;
let ans = 1;
for (let i = 0; i < N; i++) {
if (S[i] != '?' ) {
R = S.charCodeAt(i) - '0' .charCodeAt(0);
ans *= solve(cnt, R - L);
L = R;
R = 9;
cnt = 0;
}
else {
cnt++;
}
}
ans *= solve(cnt, R - L);
return ans;
}
let S = "1???2" ;
document.write(countValidStrings(S));
</script>
|
Time Complexity: O(N*10)
Auxiliary Space: O(N*10)
Efficient approach : Using DP Tabulation method ( Iterative approach )
The approach to solve this problem is same but DP tabulation(bottom-up) method is better then Dp + memoization(top-down) because memoization method needs extra stack space of recursion calls.
Steps to solve this problem :
- Create a DP of size ( len * gap) to store the solution of the subproblems and initlaize it with 0.
- Initialize the DP with base cases
- Now Iterate over subproblems to get the value of current problem form previous computation of subproblems stored in DP
- Return the final solution stored in dp[len][gap].
Implementation :
C++
#include <bits/stdc++.h>
using namespace std;
#define MAXN 100005
int dp[MAXN][10];
int solve( int len, int gap) {
int dp[len + 1][gap + 1];
memset (dp, 0, sizeof (dp));
for ( int i = 0; i <= len; i++) {
dp[i][0] = 1;
}
for ( int i = 1; i <= gap; i++) {
dp[0][i] = 1;
}
for ( int i = 1; i <= len; i++) {
for ( int j = 1; j <= gap; j++) {
for ( int k = 0; k <= j; k++) {
dp[i][j] += dp[i - 1][j - k];
}
}
}
return dp[len][gap];
}
int countValidStrings(string S)
{
memset (dp, -1, sizeof (dp));
int N = S.length();
int L = 1, R = 9;
int cnt = 0;
int ans = 1;
for ( int i = 0; i < N; i++) {
if (S[i] != '?' ) {
R = S[i] - '0' ;
ans *= solve(cnt, R - L);
L = R;
R = 9;
cnt = 0;
}
else {
cnt++;
}
}
ans *= solve(cnt, R - L);
return ans;
}
int main()
{
string S = "1???2" ;
cout << countValidStrings(S);
return 0;
}
|
Java
import java.util.*;
public class Main {
static int MAXN = 100005 ;
static int [][] dp = new int [MAXN][ 10 ];
static int solve( int len, int gap) {
int [][] dp = new int [len + 1 ][gap + 1 ];
for ( int [] row : dp) {
Arrays.fill(row, 0 );
}
for ( int i = 0 ; i <= len; i++) {
dp[i][ 0 ] = 1 ;
}
for ( int i = 1 ; i <= gap; i++) {
dp[ 0 ][i] = 1 ;
}
for ( int i = 1 ; i <= len; i++) {
for ( int j = 1 ; j <= gap; j++) {
for ( int k = 0 ; k <= j; k++) {
dp[i][j] += dp[i - 1 ][j - k];
}
}
}
return dp[len][gap];
}
static int countValidStrings(String S) {
for ( int [] row : dp) {
Arrays.fill(row, - 1 );
}
int N = S.length();
int L = 1 , R = 9 ;
int cnt = 0 ;
int ans = 1 ;
for ( int i = 0 ; i < N; i++) {
if (S.charAt(i) != '?' ) {
R = S.charAt(i) - '0' ;
ans *= solve(cnt, R - L);
L = R;
R = 9 ;
cnt = 0 ;
}
else {
cnt++;
}
}
ans *= solve(cnt, R - L);
return ans;
}
public static void main(String[] args) {
String S = "1???2" ;
System.out.println(countValidStrings(S));
}
}
|
Python
MAXN = 100005
dp = [[ - 1 for i in range ( 10 )] for j in range (MAXN)]
def solve( len , gap):
dp = [[ 0 for i in range (gap + 1 )] for j in range ( len + 1 )]
for i in range ( len + 1 ):
dp[i][ 0 ] = 1
for i in range ( 1 , gap + 1 ):
dp[ 0 ][i] = 1
for i in range ( 1 , len + 1 ):
for j in range ( 1 , gap + 1 ):
for k in range (j + 1 ):
dp[i][j] + = dp[i - 1 ][j - k]
return dp[ len ][gap]
def countValidStrings(S):
global dp
N = len (S)
L = 1
R = 9
cnt = 0
ans = 1
for i in range (N):
if S[i] ! = '?' :
R = ord (S[i]) - ord ( '0' )
ans * = solve(cnt, R - L)
L = R
R = 9
cnt = 0
else :
cnt + = 1
ans * = solve(cnt, R - L)
return ans
if __name__ = = '__main__' :
S = "1???2"
print (countValidStrings(S))
|
C#
using System;
class Program
{
static int Solve( int len, int gap)
{
int [,] dp = new int [len + 1, gap + 1];
for ( int i = 0; i <= len; i++)
{
dp[i, 0] = 1;
}
for ( int i = 1; i <= gap; i++)
{
dp[0, i] = 1;
}
for ( int i = 1; i <= len; i++)
{
for ( int j = 1; j <= gap; j++)
{
for ( int k = 0; k <= j; k++)
{
dp[i, j] += dp[i - 1, j - k];
}
}
}
return dp[len, gap];
}
static int CountValidStrings( string S)
{
int N = S.Length;
int L = 1, R = 9;
int cnt = 0;
int ans = 1;
for ( int i = 0; i < N; i++)
{
if (S[i] != '?' )
{
R = S[i] - '0' ;
ans *= Solve(cnt, R - L);
L = R;
R = 9;
cnt = 0;
}
else
{
cnt++;
}
}
ans *= Solve(cnt, R - L);
return ans;
}
static void Main()
{
string S = "1???2" ;
Console.WriteLine(CountValidStrings(S));
}
}
|
Javascript
function solve(len, gap) {
let dp = new Array(len + 1).fill().map(() => new Array(gap + 1).fill(0));
for (let i = 0; i <= len; i++) {
dp[i][0] = 1;
}
for (let i = 1; i <= gap; i++) {
dp[0][i] = 1;
}
for (let i = 1; i <= len; i++) {
for (let j = 1; j <= gap; j++) {
for (let k = 0; k <= j; k++) {
dp[i][j] += dp[i - 1][j - k];
}
}
}
return dp[len][gap];
}
function countValidStrings(S) {
let N = S.length;
let L = 1, R = 9;
let cnt = 0;
let ans = 1;
for (let i = 0; i < N; i++) {
if (S[i] != '?' ) {
R = parseInt(S[i]);
ans *= solve(cnt, R - L);
L = R;
R = 9;
cnt = 0;
}
else {
cnt++;
}
}
ans *= solve(cnt, R - L);
return ans;
}
let S = "1???2" ;
console.log(countValidStrings(S));
|
Output:
4
Time Complexity: O(N*10)
Auxiliary Space: O(N*10)
Last Updated :
07 Nov, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...