 GFG App
Open App Browser
Continue

# Count of numbers upto N having absolute difference of at most K between any two adjacent digits

Given an integer N, the task is to count the numbers up to N having an absolute difference of at most K between any two adjacent digits.
Note: Count of integer 0 for any digits is considerable.
Examples:

Input: N = 20, K = 2
Output: 15
Explanation:
The required numbers are 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 and 20. Notice that 14, 15, 16, 17, 18 and 19 all have adjacent digit’s absolute difference greater than K = 2 and thus they are not counted.
Input: N = 30, K = 3
Output: 22
Explanation:
All numbers upto 30 except 15, 16, 17, 18, 19, 26, 27, 28, 29 are accepted.

Naive Approach: The idea is to iterate till N and check for all the numbers that the difference of K exists or not. If yes then count it otherwise skip the number and keep iterating.
Time Complexity: O(N)
Auxiliary Space: O(1)
Efficient Approach: This problem can be optimized using Digit Dynamic Programming. Following are the detailed dp states for the given problem.

• In Digit Dp, we consider our number as a sequence of digits so a state position is needed so mark at which state we are currently at. In each recursive call, try to build the sequence from left to right by placing a digit from 0 to 9 and increment the position.
• Previous digit stores only those digits are put which have an absolute difference of at most K from the previous digit. So, another state needed for the previous digit.
• Tight, state tells whether the number we are trying to build has already become smaller than N, so that in the upcoming recursive calls we can place any digit from 0 to 9. Otherwise, we can place till the digit of N at the current position.
• Initialize a boolean variable Start which tells whether the number has started or not. If the number has not yet started, we can start the number by placing digits from 1 to the upper limit with respect to tight in the current position. Otherwise, recur forward without starting the number.
• In each recursive call, set the current digit with respect to the previous digit such that the absolute difference between them never exceeds K. In the base case, return 1 if reached the last position.

Below is the implementation of the above approach:

## C++

 `// C++ program to get the count` `// of numbers upto N having` `// absolute difference at most K` `// between any two adjacent digits`   `#include ` `using` `namespace` `std;`   `// Table to store solution` `// of each subproblem` `long` `long` `dp;`   `// Function to calculate` `// all possible numbers` `long` `long` `possibleNumbers(` `    ``int` `pos, ``int` `previous, ``bool` `tight,` `    ``bool` `start, string N, ``int` `K)` `{` `    ``// Check if position reaches end that is` `    ``// is equal to length of N` `    ``if` `(pos == N.length())` `        ``return` `1;`   `    ``// Check if the result is` `    ``// already computed` `    ``// simply return it` `    ``if` `(dp[pos][previous][tight][start] != -1)` `        ``return` `dp[pos][previous][tight][start];`   `    ``int` `res = 0;`   `    ``// Maximum limit upto which we can place` `    ``// digit. If tight is false, means number has` `    ``// already become smaller so we can place` `    ``// any digit, otherwise N[pos]` `    ``int` `upper_limit` `        ``= (tight)` `              ``? (N[pos] - ``'0'``)` `              ``: 9;`   `    ``int` `new_tight;`   `    ``// Check if start is false the number` `    ``// has not started yet` `    ``if` `(!start) {`   `        ``// Check if we do not start` `        ``// the number at pos` `        ``// then recur forward` `        ``res = possibleNumbers(` `            ``pos + 1, previous,` `            ``false``, ``false``, N, K);`   `        ``// If we start the number` `        ``// we can place any digit` `        ``// from 1 to upper_limit` `        ``for` `(``int` `i = 1; i <= upper_limit; i++) {`   `            ``// Finding the new tight` `            ``new_tight` `                ``= (tight` `                   ``&& i == upper_limit)` `                      ``? 1` `                      ``: 0;` `            ``res += possibleNumbers(` `                ``pos + 1, i, new_tight,` `                ``true``, N, K);` `        ``}` `    ``}`   `    ``// Condition if the number` `    ``// has already started` `    ``else` `{`   `        ``// We can place digit upto` `        ``// upperbound & absolute difference` `        ``// with previous digit must` `        ``// be atmost K` `        ``for` `(``int` `i = 0; i <= upper_limit; i++) {`   `            ``new_tight = (tight` `                         ``&& i == upper_limit)` `                            ``? 1` `                            ``: 0;` `            ``// Absolute difference atmost K` `            ``if` `(``abs``(i - previous) <= K)` `                ``res += possibleNumbers(` `                    ``pos + 1, i,` `                    ``new_tight, ``true``, N, K);` `        ``}` `    ``}`   `    ``// Store the solution` `    ``// to this subproblem` `    ``dp[pos][previous][tight][start] = res;`   `    ``return` `dp[pos][previous][tight][start];` `}`   `// Driver code` `int` `main(``void``)` `{`   `    ``string N = ``"20"``;` `    ``int` `K = 2;`   `    ``// Initialising the` `    ``// table with -1` `    ``memset``(dp, -1, ``sizeof` `dp);`   `    ``// Function call` `    ``cout << possibleNumbers(` `                ``0, 0, ``true``,` `                ``false``, N, K)` `         ``<< endl;` `}`

## Java

 `// Java program to get the count` `// of numbers upto N having` `// absolute difference at most K` `// between any two adjacent digits` `import` `java.util.*;`   `class` `GFG{`   `// Table to store solution` `// of each subproblem` `static` `int` `[][][][]dp = ``new` `int``[``1002``][``10``][``2``][``2``];`   `// Function to calculate` `// all possible numbers` `static` `int` `possibleNumbers(``int` `pos, ``int` `previous, ` `                           ``int` `tight, ``int` `start,` `                            ``String N, ``int` `K)` `{` `    `  `    ``// Check if position reaches end ` `    ``// that is equal to length of N` `    ``if` `(pos == N.length())` `        ``return` `1``;`   `    ``// Check if the result is already` `    ``// computed simply return it` `    ``if` `(dp[pos][previous][tight][start] != -``1``)` `        ``return` `dp[pos][previous][tight][start];`   `    ``int` `res = ``0``;`   `    ``// Maximum limit upto which we can ` `    ``// place digit. If tight is false, ` `    ``// means number has already become` `    ``// smaller so we can place` `    ``// any digit, otherwise N[pos]` `    ``int` `upper_limit = (tight == ``1``) ? ` `                      ``(N.charAt(pos) - ``'0'``) : ``9``;` `                      `  `    ``int` `new_tight;`   `    ``// Check if start is false the number` `    ``// has not started yet` `    ``if` `(start == ``0``)` `    ``{` `        `  `        ``// Check if we do not start` `        ``// the number at pos` `        ``// then recur forward` `        ``res = possibleNumbers(pos + ``1``, previous,` `                              ``0``, ``0``, N, K);`   `        ``// If we start the number` `        ``// we can place any digit` `        ``// from 1 to upper_limit` `        ``for``(``int` `i = ``1``; i <= upper_limit; i++)` `        ``{` `            `  `            ``// Finding the new tight` `            ``new_tight = (tight > ``0` `&& ` `                         ``i == upper_limit) ? ``1` `: ``0``;` `            ``res += possibleNumbers(pos + ``1``, i,` `                                   ``new_tight,` `                                   ``1``, N, K);` `        ``}` `    ``}` `    `  `    ``// Condition if the number` `    ``// has already started` `    ``else` `    ``{` `        `  `        ``// We can place digit upto` `        ``// upperbound & absolute difference` `        ``// with previous digit must` `        ``// be atmost K` `        ``for``(``int` `i = ``0``; i <= upper_limit; i++)` `        ``{` `            ``new_tight = (tight > ``0` `&& ` `                         ``i == upper_limit) ? ``1` `: ``0``;` `                         `  `            ``// Absolute difference atmost K` `            ``if` `(Math.abs(i - previous) <= K)` `                ``res += possibleNumbers(pos + ``1``, i,` `                                       ``new_tight, ``1``,` `                                       ``N, K);` `        ``}` `    ``}`   `    ``// Store the solution` `    ``// to this subproblem` `    ``dp[pos][previous][tight][start] = res;`   `    ``return` `dp[pos][previous][tight][start];` `}`   `// Driver code` `public` `static` `void` `main(String[] args) ` `{` `    ``String N = ``"20"``;` `    ``int` `K = ``2``;`   `    ``// Initialising the` `    ``// table with -1` `    ``for``(``int` `i = ``0``; i < ``1002``; i++)` `        ``for``(``int` `j = ``0``; j < ``10``; j++)` `            ``for``(``int` `k = ``0``; k < ``2``; k++)` `                ``for``(``int` `l = ``0``; l < ``2``; l++)` `                    ``dp[i][j][k][l] = -``1``;`   `    ``// Function call` `    ``System.out.print(possibleNumbers(``0``, ``0``, ``1``, ``0``, ` `                                     ``N, K) + ``"\n"``);` `}` `}`   `// This code is contributed by Princi Singh`

## Python3

 `# Python3 program to get the count of ` `# numbers upto N having absolute` `# difference at most K between any ` `# two adjacent digits`   `# Table to store solution` `# of each subproblem` `dp ``=` `[[[[ ``-``1` `for` `i ``in` `range``(``2``)]` `             ``for` `j ``in` `range``(``2``)]` `             ``for` `i ``in` `range``(``10``)]` `             ``for` `j ``in` `range``(``1002``)]`   `# Function to calculate` `# all possible numbers` `def` `possibleNumber(pos, previous, tight,` `                   ``start, N, K):`   `    ``# Check if position reaches end ` `    ``# that is equal to length of N` `    ``if``(pos ``=``=` `len``(N)):` `        ``return` `1`   `    ``# Check if the result is` `    ``# already computed` `    ``# simply return it` `    ``if``(dp[pos][previous][tight][start] !``=` `-``1``):` `        ``return` `dp[pos][previous][tight][start]`   `    ``res ``=` `0`   `    ``# Maximum limit upto which we can place` `    ``# digit. If tight is false, means number has` `    ``# already become smaller so we can place` `    ``# any digit, otherwise N[pos]` `    ``if``(tight):` `        ``upper_limit ``=` `ord``(N[pos]) ``-` `ord``(``'0'``)` `    ``else``:` `        ``upper_limit ``=` `9`   `    ``# Check if start is false the number` `    ``# has not started yet` `    ``if``(``not` `start):`   `        ``# Check if we do not start` `        ``# the number at pos` `        ``# then recur forward` `        ``res ``=` `possibleNumber(pos ``+` `1``, previous,` `                             ``False``, ``False``, N, K)`   `        ``# If we start the number` `        ``# we can place any digit` `        ``# from 1 to upper_limit` `        ``for` `i ``in` `range``(``1``, upper_limit ``+` `1``):`   `            ``# Finding the new tight` `            ``if``(tight ``and` `i ``=``=` `upper_limit):` `                ``new_tight ``=` `1` `            ``else``:` `                ``new_tight ``=` `0`   `            ``res ``+``=` `possibleNumber(pos ``+` `1``, i, ` `                                  ``new_tight,` `                                  ``True``, N, K)` `                                  `  `    ``# Condition if the number` `    ``# has already started` `    ``else``:` `        `  `        ``# We can place digit upto` `        ``# upperbound & absolute ` `        ``# difference with previous` `        ``# digit must be atmost K` `        ``for` `i ``in` `range``(upper_limit ``+` `1``):` `            ``if``(tight ``and` `i ``=``=` `upper_limit):` `                ``new_tight ``=` `1` `            ``else``:` `                ``new_tight ``=` `0`   `            ``# Absolute difference atmost K` `            ``if``(``abs``(i ``-` `previous) <``=` `K):` `                ``res ``+``=` `possibleNumber(pos ``+` `1``, i,` `                                      ``new_tight,` `                                        ``True``, N, K)`   `    ``# Store the solution to this subproblem` `    ``dp[pos][previous][tight][start] ``=` `res`   `    ``return` `dp[pos][previous][tight][start]`   `# Driver code` `if` `__name__ ``=``=` `'__main__'``:` `    `  `    ``N ``=` `"20"` `    ``K ``=` `2` `    `  `    ``# Function call` `    ``print``(possibleNumber(``0``, ``0``, ``True``,` `                         ``False``, N, K))`   `# This code is contributed by Shivam Singh`

## C#

 `// C# program to get the count` `// of numbers upto N having` `// absolute difference at most K` `// between any two adjacent digits` `using` `System;`   `class` `GFG{`   `// Table to store solution` `// of each subproblem` `static` `int` `[,,,]dp = ``new` `int``[1002, 10, 2, 2];`   `// Function to calculate` `// all possible numbers` `static` `int` `possibleNumbers(``int` `pos, ``int` `previous, ` `                           ``int` `tight, ``int` `start,` `                            ``String N, ``int` `K)` `{` `    `  `    ``// Check if position reaches end ` `    ``// that is equal to length of N` `    ``if` `(pos == N.Length)` `        ``return` `1;`   `    ``// Check if the result is already` `    ``// computed simply return it` `    ``if` `(dp[pos, previous, tight, start] != -1)` `        ``return` `dp[pos, previous, tight, start];`   `    ``int` `res = 0;`   `    ``// Maximum limit upto which we can ` `    ``// place digit. If tight is false, ` `    ``// means number has already become` `    ``// smaller so we can place` `    ``// any digit, otherwise N[pos]` `    ``int` `upper_limit = (tight == 1) ? ` `                      ``(N[pos] - ``'0'``) : 9;` `                    `  `    ``int` `new_tight;`   `    ``// Check if start is false the number` `    ``// has not started yet` `    ``if` `(start == 0)` `    ``{` `        `  `        ``// Check if we do not start` `        ``// the number at pos` `        ``// then recur forward` `        ``res = possibleNumbers(pos + 1, previous,` `                              ``0, 0, N, K);`   `        ``// If we start the number` `        ``// we can place any digit` `        ``// from 1 to upper_limit` `        ``for``(``int` `i = 1; i <= upper_limit; i++)` `        ``{` `            `  `            ``// Finding the new tight` `            ``new_tight = (tight > 0 && ` `                         ``i == upper_limit) ? 1 : 0;` `            ``res += possibleNumbers(pos + 1, i,` `                                   ``new_tight,` `                                   ``1, N, K);` `        ``}` `    ``}` `    `  `    ``// Condition if the number` `    ``// has already started` `    ``else` `    ``{` `        `  `        ``// We can place digit upto` `        ``// upperbound & absolute difference` `        ``// with previous digit must` `        ``// be atmost K` `        ``for``(``int` `i = 0; i <= upper_limit; i++)` `        ``{` `            ``new_tight = (tight > 0 && ` `                         ``i == upper_limit) ? 1 : 0;` `                        `  `            ``// Absolute difference atmost K` `            ``if` `(Math.Abs(i - previous) <= K)` `                ``res += possibleNumbers(pos + 1, i,` `                                       ``new_tight, 1,` `                                       ``N, K);` `        ``}` `    ``}`   `    ``// Store the solution` `    ``// to this subproblem` `    ``dp[pos, previous, tight, start] = res;`   `    ``return` `dp[pos, previous, tight, start];` `}`   `// Driver code` `public` `static` `void` `Main(String[] args) ` `{` `    ``String N = ``"20"``;` `    ``int` `K = 2;`   `    ``// Initialising the` `    ``// table with -1` `    ``for``(``int` `i = 0; i < 1002; i++)` `        ``for``(``int` `j = 0; j < 10; j++)` `            ``for``(``int` `k = 0; k < 2; k++)` `                ``for``(``int` `l = 0; l < 2; l++)` `                    ``dp[i, j, k, l] = -1;`   `    ``// Function call` `    ``Console.Write(possibleNumbers(0, 0, 1, 0, ` `                                  ``N, K) + ``"\n"``);` `}` `}`   `// This code is contributed by amal kumar choubey`

## Javascript

 ``

Output:

`15`

Time Complexity: O( D * 10 * 2 * 2 * 10), considering N has D digits.

My Personal Notes arrow_drop_up