Given a positive integer N, the task is to find the number of N-digit numbers such that every digit is smaller than its adjacent digits.
Examples:
Input: N = 1
Output: 10
Explanation: All numbers from [0 – 9] satisfy the condition as there is only one digit.
Input: N = 3
Output: 525
Naive Approach: The simplest approach to solve the given problem is to iterate over all possible N-digit numbers and for each such number, check if all its digits satisfy the given criteria or not. If found to be true, then count these numbers. After checking for all the numbers print the total count obtained.
Time Complexity: O(10N*N)
Auxiliary Space: O(1)
Efficient Approach: The above approach can also be optimized by using Dynamic Programming because it has overlapping subproblems and optimal substructure. The subproblems can be stored in dp[][][] table using memoization where dp[i][prev][sign] stores the result from the ith position till the end, when the previous digit selected, is prev and the variable sign is used to indicate if the current digit must be lesser or greater than the previous digit. Follow the steps below to solve the problem:
- Define a recursive function, say, countOfNumbers(digit, prev, sign) with three parameters: digit, sign and prev.
- Check for the base cases, i.e., if the value of i is equal to N then return 1 as a valid N-digit number is formed.
- Initialize a variable, say, val = 0, to store all possible counts of N-digit numbers.
- If i is 0, then any digit from [1 – 9] can be placed, and also if N = 1, then 0 can be placed as well.
- If i is 1, then any digit from [0 – 9] can be placed such that the current digit is not equal to the previous one.
- If the value of the sign is 1, then place the current digit such that it is less than the previous digit and change the sign to 0 for the next recursive call.
- If the value of the sign is 0, then place the current digit such that it is more than the previous digit and change the sign to 1 for the next recursive call.
- After making a valid placement, recursively call the countOfNumbers function for index (digit + 1).
- Return the sum of all possible valid placements of digits as the result of each current recursive call.
- After the above steps, print the value returned by the function countOfNumbers(0, N, 0, 0) as the resultant count.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int dp[100][10][2];
int solve( int i, int n, int prev, bool sign)
{
if (i == n) {
return 1;
}
int & val = dp[i][prev][sign];
if (val != -1)
return val;
val = 0;
if (i == 0) {
for ( int digit = (n == 1 ? 0 : 1);
digit <= 9;
++digit) {
val += solve(i + 1, n,
digit, sign);
}
}
else if (i == 1) {
for ( int digit = 0; digit <= 9;
++digit) {
if (digit != prev) {
val += solve(i + 1, n, digit,
(digit > prev));
}
}
}
else {
if (sign == 1) {
for ( int digit = prev - 1;
digit >= 0;
--digit) {
val += solve(i + 1, n,
digit, 0);
}
}
else {
for ( int digit = prev + 1;
digit <= 9;
++digit) {
val += solve(i + 1, n,
digit, 1);
}
}
}
return val;
}
void countNdigitNumber( int N)
{
memset (dp, -1, sizeof dp);
cout << solve(0, N, 0, 0);
}
int main()
{
int N = 3;
countNdigitNumber(N);
return 0;
}
|
Java
import java.util.*;
public class MyClass
{
static int [][][] dp = new int [ 100 ][ 10 ][ 2 ];
static int solve( int i, int n, int prev, int sign)
{
if (i == n) {
return 1 ;
}
int val = dp[i][prev][sign];
if (val != - 1 )
return val;
val = 0 ;
if (i == 0 ) {
for ( int digit = (n == 1 ? 0 : 1 );
digit <= 9 ;
++digit) {
val += solve(i + 1 , n,
digit, sign);
}
}
else if (i == 1 ) {
for ( int digit = 0 ; digit <= 9 ;
++digit) {
if (digit != prev) {
val += solve(i + 1 , n, digit,((digit > prev)? 1 : 0 ));
}
}
}
else {
if (sign == 1 ) {
for ( int digit = prev - 1 ;
digit >= 0 ;
--digit) {
val += solve(i + 1 , n,
digit, 0 );
}
}
else {
for ( int digit = prev + 1 ;
digit <= 9 ;
++digit) {
val += solve(i + 1 , n,
digit, 1 );
}
}
}
return val;
}
static void countNdigitNumber( int N)
{
for ( int [][] row : dp)
{
for ( int [] rowColumn : row)
{
Arrays.fill(rowColumn, - 1 );
}
}
System.out.println(solve( 0 , N, 0 , 0 ));
}
public static void main(String args[])
{
int N = 3 ;
countNdigitNumber(N);
}
}
|
Python3
dp = [[[ - 1 for x in range ( 2 )] for y in range ( 10 )] for z in range ( 100 )]
def solve(i, n, prev, sign):
if (i = = n):
return 1
val = dp[i][prev][sign]
if (val ! = - 1 ):
return val
val = 0
if (i = = 0 ):
if (n = = 1 ):
digit = 0
else :
digit = 1
while digit < = 9 :
val + = solve(i + 1 , n,
digit, sign)
digit + = 1
elif (i = = 1 ):
for digit in range ( 10 ):
if (digit ! = prev):
val + = solve(i + 1 , n, digit,
(digit > prev))
else :
if (sign = = 1 ):
for digit in range (prev - 1 ,
- 1 , - 1 ):
val + = solve(i + 1 , n,
digit, 0 )
else :
for digit in range (prev + 1 , 10 ):
val + = solve(i + 1 , n,
digit, 1 )
return val
def countNdigitNumber(N):
print (solve( 0 , N, 0 , 0 ))
if __name__ = = "__main__" :
N = 3
countNdigitNumber(N)
|
C#
using System;
using System.Collections.Generic;
public class MyClass
{
static int [,,] dp = new int [100,10,2];
static int solve( int i, int n, int prev, int sign)
{
if (i == n) {
return 1;
}
int val = dp[i,prev,sign];
if (val != -1)
return val;
val = 0;
if (i == 0) {
for ( int digit = (n == 1 ? 0 : 1);
digit <= 9;
++digit) {
val += solve(i + 1, n,
digit, sign);
}
}
else if (i == 1) {
for ( int digit = 0; digit <= 9;
++digit) {
if (digit != prev) {
val += solve(i + 1, n, digit,((digit > prev)?1:0));
}
}
}
else {
if (sign == 1) {
for ( int digit = prev - 1;
digit >= 0;
--digit) {
val += solve(i + 1, n,
digit, 0);
}
}
else {
for ( int digit = prev + 1;
digit <= 9;
++digit) {
val += solve(i + 1, n,
digit, 1);
}
}
}
return val;
}
static void countNdigitNumber( int N)
{
for ( int i = 0;i<100;i++)
{
for ( int j = 0; j < 10; j++) {
for ( int k = 0; k < 2; k++)
dp[i,j,k] = -1;
}
}
Console.WriteLine(solve(0, N, 0, 0));
}
public static void Main(String []args)
{
int N = 3;
countNdigitNumber(N);
}
}
|
Javascript
<script>
var dp = Array(100).fill().map(()=>Array(10).fill().map(()=>Array(2).fill(-1)));
function solve(i , n , prev , sign) {
if (i == n) {
return 1;
}
var val = dp[i][prev][sign];
if (val != -1)
return val;
val = 0;
if (i == 0) {
for ( var digit = (n == 1 ? 0 : 1); digit <= 9; ++digit) {
val += solve(i + 1, n, digit, sign);
}
}
else if (i == 1) {
for ( var digit = 0; digit <= 9; ++digit) {
if (digit != prev) {
val += solve(i + 1, n, digit, ((digit > prev) ? 1 : 0));
}
}
}
else {
if (sign == 1) {
for ( var digit = prev - 1; digit >= 0; --digit) {
val += solve(i + 1, n, digit, 0);
}
}
else {
for ( var digit = prev + 1; digit <= 9; ++digit) {
val += solve(i + 1, n, digit, 1);
}
}
}
return val;
}
function countNdigitNumber(N) {
document.write(solve(0, N, 0, 0));
}
var N = 3;
countNdigitNumber(N);
</script>
|
Time Complexity: O(N)
Auxiliary Space: O(N)
Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!
Last Updated :
17 Nov, 2021
Like Article
Save Article