Given an integer n, return all numbers less than or equal to n in increasing order such that the absolute difference between adjacent digits of every number is exactly 1.
Note: Only numbers with at least two digits are considered valid.
Examples:
Input: n = 20
Output: [10, 12]
Explanation: The absolute difference between adjacent digits in 10 is |1 - 0| = 1, and in 12 is |1 - 2| = 1.Input: n = 9
Output: []
Explanation: No such valid number exist in the range 1 to 9.
Table of Content
[Naive Approach] Check Every Number - O(n × d) Time and O(1) Space
The idea is to iterate through every number from 10 to n and check whether the absolute difference between every pair of adjacent digits is exactly 1. If the condition is satisfied, include the number in the result; otherwise, ignore it.
Working of Approach:
- Traverse every number from 10 to n.
- Extract adjacent digits one by one using modulo and division.
- Check whether the absolute difference of every adjacent digit pair is 1.
- If all pairs satisfy the condition, add the number to the answer.
- Return the final list.
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
// Function to check whether adjacent digits differ by exactly 1.
bool isValid(int num)
{
while (num >= 10)
{
int last = num % 10;
int secondLast = (num / 10) % 10;
if (abs(last - secondLast) != 1)
return false;
num /= 10;
}
return true;
}
vector<int> absDifOne(int n)
{
vector<int> res;
// Check every number from 10 to n.
for (int i = 10; i <= n; i++)
{
if (isValid(i))
res.push_back(i);
}
return res;
}
int main()
{
int n = 20;
vector<int> res = absDifOne(n);
cout << "[";
for (int i = 0; i < res.size(); i++)
{
cout << res[i];
if (i + 1 < res.size())
cout << ", ";
}
cout << "]";
return 0;
}
import java.util.ArrayList;
import java.util.Arrays;
public class GFG {
// Function to check whether adjacent digits differ by
// exactly 1.
public static boolean isValid(int num)
{
while (num >= 10) {
int last = num % 10;
int secondLast = (num / 10) % 10;
if (Math.abs(last - secondLast) != 1)
return false;
num /= 10;
}
return true;
}
public static ArrayList<Integer> absDifOne(int n)
{
ArrayList<Integer> res = new ArrayList<>();
// Check every number from 10 to n.
for (int i = 10; i <= n; i++) {
if (isValid(i))
res.add(i);
}
return res;
}
public static void main(String[] args)
{
int n = 20;
ArrayList<Integer> res = absDifOne(n);
System.out.println(res);
}
}
def isValid(num):
while num >= 10:
last = num % 10
secondLast = (num // 10) % 10
if abs(last - secondLast) != 1:
return False
num //= 10
return True
def absDifOne(n):
res = []
# Check every number from 10 to n.
for i in range(10, n + 1):
if isValid(i):
res.append(i)
return res
if __name__ == '__main__':
n = 20
res = absDifOne(n)
print(res)
using System;
using System.Collections.Generic;
class GFG {
// Function to check whether adjacent digits differ by
// exactly 1.
static bool isValid(int num)
{
while (num >= 10) {
int last = num % 10;
int secondLast = (num / 10) % 10;
if (Math.Abs(last - secondLast) != 1)
return false;
num /= 10;
}
return true;
}
static List<int> absDifOne(int n)
{
List<int> res = new List<int>();
// Check every number from 10 to n.
for (int i = 10; i <= n; i++) {
if (isValid(i))
res.Add(i);
}
return res;
}
static void Main(string[] args)
{
int n = 20;
List<int> res = absDifOne(n);
Console.Write("[");
for (int i = 0; i < res.Count; i++) {
Console.Write(res[i]);
if (i + 1 < res.Count)
Console.Write(", ");
}
Console.Write("]");
}
}
function isValid(num)
{
while (num >= 10) {
let last = num % 10;
let secondLast = Math.floor(num / 10) % 10;
if (Math.abs(last - secondLast) !== 1)
return false;
num = Math.floor(num / 10);
}
return true;
}
function absDifOne(n)
{
let res = [];
// Check every number from 10 to n.
for (let i = 10; i <= n; i++) {
if (isValid(i))
res.push(i);
}
return res;
}
// Driver Code
let n = 20;
let res = absDifOne(n);
console.log(res);
Output
[10, 12]
Time Complexity: O(n × d), where d is the number of digits.
Space Complexity: O(1)
[Expected Approach] Generate Valid Numbers using BFS - O(k) Time and O(k) Space
The idea is to generate only the valid numbers instead of checking every number. Start BFS from all one-digit numbers (1 to 9). For every number, append lastDigit - 1 and lastDigit + 1 whenever possible to form the next valid numbers. Continue until the generated numbers become greater than n.
For every stepping number curr, let lastDigit = curr % 10. The next possible numbers can only be formed by appending:
- lastDigit - 1
- lastDigit + 1
This is because the newly formed last adjacent pair must differ by exactly 1.
Suppose the last digit of curr is d.. Since curr is already a stepping number, all its previous adjacent digit pairs already satisfy the condition. Appending only changes the last adjacent pair, which also has a difference of 1. Therefore, the newly formed number is guaranteed to be a valid stepping number.
The only exceptions occur when the last digit is:
- 0 -> Only 1 can be appended.
- 9 -> Only 8 can be appended.
Thus, every stepping number generates at most two valid stepping numbers, making BFS an efficient way to enumerate all stepping numbers up to n.
Working of Approach:
- Push all one-digit numbers (1 to 9) into a queue.
- Remove one number at a time from the queue.
- If the current number has at least two digits and is not greater than n, store it in the answer.
- Generate new numbers by appending lastDigit - 1 and lastDigit + 1.
- Repeat until the queue becomes empty.
Let us understand with an example:
Input: n = 20
- Initialize the queue with all one-digit numbers: 1, 2, 3, ..., 9.
- Remove 1 from the queue and generate 10 and 12 by appending 0 and 2; both are added to the queue.
- Continue processing the remaining numbers in the queue. Numbers such as 21, 23, 32, and so on are generated, but since they are greater than 20, they are ignored.
- Whenever a number greater than 20 is removed from the queue, it is ignored and no further processing is done for it.
- The only generated valid numbers less than or equal to 20 are 10 and 12, so the output is [10, 12].
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
vector<int> absDifOne(int n)
{
vector<int> res;
queue<int> q;
// Push all single-digit numbers into the queue.
for (int i = 1; i <= 9; i++)
{
q.push(i);
}
while (!q.empty())
{
int curr = q.front();
q.pop();
// Skip numbers greater than n.
if (curr > n)
{
continue;
}
// Store valid numbers having at least two digits.
if (curr > 9)
{
res.push_back(curr);
}
int lastDigit = curr % 10;
// Generate the next number with lastDigit - 1.
if (lastDigit > 0)
{
q.push(curr * 10 + lastDigit - 1);
}
// Generate the next number with lastDigit + 1.
if (lastDigit < 9)
{
q.push(curr * 10 + lastDigit + 1);
}
}
return res;
}
int main()
{
int n = 20;
vector<int> res = absDifOne(n);
cout << "[";
for (int i = 0; i < res.size(); i++)
{
cout << res[i];
if (i + 1 < res.size())
cout << ", ";
}
cout << "]";
return 0;
}
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
public class GFG {
public static ArrayList<Integer> absDifOne(int n)
{
ArrayList<Integer> res = new ArrayList<>();
Queue<Integer> q = new LinkedList<>();
// Push all single-digit numbers into the queue.
for (int i = 1; i <= 9; i++) {
q.add(i);
}
while (!q.isEmpty()) {
int curr = q.poll();
// Skip numbers greater than n.
if (curr > n) {
continue;
}
// Store valid numbers having at least two
// digits.
if (curr > 9) {
res.add(curr);
}
int lastDigit = curr % 10;
// Generate the next number with lastDigit - 1.
if (lastDigit > 0) {
q.add(curr * 10 + lastDigit - 1);
}
// Generate the next number with lastDigit + 1.
if (lastDigit < 9) {
q.add(curr * 10 + lastDigit + 1);
}
}
return res;
}
public static void main(String[] args)
{
int n = 20;
ArrayList<Integer> res = absDifOne(n);
System.out.print("[");
for (int i = 0; i < res.size(); i++) {
System.out.print(res.get(i));
if (i + 1 < res.size())
System.out.print(", ");
}
System.out.print("]");
}
}
from collections import deque
def absDifOne(n):
res = []
q = deque()
# Push all single-digit numbers into the queue.
for i in range(1, 10):
q.append(i)
while q:
curr = q.popleft()
# Skip numbers greater than n.
if curr > n:
continue
# Store valid numbers having at least two digits.
if curr > 9:
res.append(curr)
lastDigit = curr % 10
# Generate the next number with lastDigit - 1.
if lastDigit > 0:
q.append(curr * 10 + lastDigit - 1)
# Generate the next number with lastDigit + 1.
if lastDigit < 9:
q.append(curr * 10 + lastDigit + 1)
return res
if __name__ == "__main__":
n = 20
res = absDifOne(n)
print('[', end='')
for i in range(len(res)):
print(res[i], end='')
if i + 1 < len(res):
print(', ', end='')
print(']')
using System;
using System.Collections.Generic;
using System.Linq;
public class GFG {
public static List<int> absDifOne(int n)
{
List<int> res = new List<int>();
Queue<int> q = new Queue<int>();
// Push all single-digit numbers into the queue.
for (int i = 1; i <= 9; i++) {
q.Enqueue(i);
}
while (q.Count > 0) {
int curr = q.Dequeue();
// Skip numbers greater than n.
if (curr > n) {
continue;
}
// Store valid numbers having at least two
// digits.
if (curr > 9) {
res.Add(curr);
}
int lastDigit = curr % 10;
// Generate the next number with lastDigit - 1.
if (lastDigit > 0) {
q.Enqueue(curr * 10 + lastDigit - 1);
}
// Generate the next number with lastDigit + 1.
if (lastDigit < 9) {
q.Enqueue(curr * 10 + lastDigit + 1);
}
}
return res;
}
public static void Main()
{
int n = 20;
List<int> res = absDifOne(n);
Console.Write("[");
for (int i = 0; i < res.Count; i++) {
Console.Write(res[i]);
if (i + 1 < res.Count)
Console.Write(", ");
}
Console.Write("]");
}
}
function absDifOne(n)
{
let res = [];
let q = [];
// Push all single-digit numbers into the queue.
for (let i = 1; i <= 9; i++) {
q.push(i);
}
while (q.length > 0) {
let curr = q.shift();
// Skip numbers greater than n.
if (curr > n) {
continue;
}
// Store valid numbers having at least two digits.
if (curr > 9) {
res.push(curr);
}
let lastDigit = curr % 10;
// Generate the next number with lastDigit - 1.
if (lastDigit > 0) {
q.push(curr * 10 + lastDigit - 1);
}
// Generate the next number with lastDigit + 1.
if (lastDigit < 9) {
q.push(curr * 10 + lastDigit + 1);
}
}
return res;
}
// Driver Code
let n = 20;
let res = absDifOne(n);
console.log("[" + res.join(", ") + "]");
Output
[10, 12]
Time Complexity: O(k), where k is the total number of stepping numbers generated that are less than or equal to n. Each generated stepping number is processed exactly once.
Space Complexity: O(k)
[Alternative Approach] Using DFS / Backtracking - O(k log k) Time and O(d) Space
The idea is to recursively generate only the valid numbers instead of checking every number. Start DFS from every one-digit number (1 to 9). For a number ending with digit d, recursively append d - 1 and d + 1 whenever they are valid digits. After generating all valid numbers, sort them to get the required increasing order.
Working of Approach:
- Start DFS from each digit from 1 to 9.
- If the current number is greater than n, stop that recursive path.
- If the current number has at least two digits, store it.
- Recursively generate the next numbers by appending lastDigit - 1 and lastDigit + 1.
- Sort the generated numbers and return the result.
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
// DFS function to generate valid numbers.
void dfs(long long curr, int n, vector<int> &res)
{
// Stop if number exceeds n.
if (curr > n)
return;
// Store valid numbers having at least two digits.
if (curr >= 10)
res.push_back(curr);
int lastDigit = curr % 10;
// Generate the next number with lastDigit - 1.
if (lastDigit > 0)
dfs(curr * 10 + lastDigit - 1, n, res);
// Generate the next number with lastDigit + 1.
if (lastDigit < 9)
dfs(curr * 10 + lastDigit + 1, n, res);
}
vector<int> absDifOne(int n)
{
vector<int> res;
// Start DFS from every one-digit number.
for (int i = 1; i <= 9; i++)
dfs(i, n, res);
// Sort to get increasing order.
sort(res.begin(), res.end());
return res;
}
int main()
{
int n = 20;
vector<int> res = absDifOne(n);
cout << "[";
for (int i = 0; i < res.size(); i++)
{
cout << res[i];
if (i + 1 < res.size())
cout << ", ";
}
cout << "]";
return 0;
}
import java.util.ArrayList;
import java.util.Collections;
public class GFG {
// DFS function to generate valid numbers.
private static void dfs(long curr, int n,
ArrayList<Integer> res)
{
// Stop if number exceeds n.
if (curr > n)
return;
// Store valid numbers having at least two digits.
if (curr >= 10)
res.add((int)curr);
int lastDigit = (int)(curr % 10);
// Generate the next number with lastDigit - 1.
if (lastDigit > 0)
dfs(curr * 10 + lastDigit - 1, n, res);
// Generate the next number with lastDigit + 1.
if (lastDigit < 9)
dfs(curr * 10 + lastDigit + 1, n, res);
}
public static ArrayList<Integer> absDifOne(int n)
{
ArrayList<Integer> res = new ArrayList<>();
// Start DFS from every one-digit number.
for (int i = 1; i <= 9; i++)
dfs(i, n, res);
// Sort to get increasing order.
Collections.sort(res);
return res;
}
public static void main(String[] args)
{
int n = 20;
ArrayList<Integer> res = absDifOne(n);
System.out.print("[");
for (int i = 0; i < res.size(); i++) {
System.out.print(res.get(i));
if (i + 1 < res.size())
System.out.print(", ");
}
System.out.print("]");
}
}
def dfs(curr, n, res):
# Stop if number exceeds n.
if curr > n:
return
# Store valid numbers having at least two digits.
if curr >= 10:
res.append(int(curr))
lastDigit = curr % 10
# Generate the next number with lastDigit - 1.
if lastDigit > 0:
dfs(curr * 10 + lastDigit - 1, n, res)
# Generate the next number with lastDigit + 1.
if lastDigit < 9:
dfs(curr * 10 + lastDigit + 1, n, res)
def absDifOne(n):
res = []
# Start DFS from every one-digit number.
for i in range(1, 10):
dfs(i, n, res)
# Sort to get increasing order.
res.sort()
return res
if __name__ == '__main__':
n = 20
res = absDifOne(n)
print('[', end='')
for i in range(len(res)):
print(res[i], end='' if i == len(res) - 1 else ', ')
print(']')
using System;
using System.Collections.Generic;
using System.Linq;
public class GFG {
// DFS function to generate valid numbers.
private static void dfs(long curr, int n, List<int> res)
{
// Stop if number exceeds n.
if (curr > n)
return;
// Store valid numbers having at least two digits.
if (curr >= 10)
res.Add((int)curr);
int lastDigit = (int)(curr % 10);
// Generate the next number with lastDigit - 1.
if (lastDigit > 0)
dfs(curr * 10 + lastDigit - 1, n, res);
// Generate the next number with lastDigit + 1.
if (lastDigit < 9)
dfs(curr * 10 + lastDigit + 1, n, res);
}
public static List<int> absDifOne(int n)
{
List<int> res = new List<int>();
// Start DFS from every one-digit number.
for (int i = 1; i <= 9; i++)
dfs(i, n, res);
// Sort to get increasing order.
res.Sort();
return res;
}
public static void Main()
{
int n = 20;
List<int> res = absDifOne(n);
Console.Write('[');
for (int i = 0; i < res.Count; i++) {
Console.Write(res[i]);
if (i + 1 < res.Count)
Console.Write(", ");
}
Console.Write(']');
}
}
// DFS function to generate valid numbers.
function dfs(curr, n, res)
{
// Stop if number exceeds n.
if (curr > n)
return;
// Store valid numbers having at least two digits.
if (curr >= 10)
res.push(curr);
let lastDigit = curr % 10;
// Generate the next number with lastDigit - 1.
if (lastDigit > 0)
dfs(curr * 10 + lastDigit - 1, n, res);
// Generate the next number with lastDigit + 1.
if (lastDigit < 9)
dfs(curr * 10 + lastDigit + 1, n, res);
}
function absDifOne(n)
{
let res = [];
// Start DFS from every one-digit number.
for (let i = 1; i <= 9; i++)
dfs(i, n, res);
// Sort to get increasing order.
res.sort((a, b) => a - b);
return res;
}
// Driver code
let n = 20;
let res = absDifOne(n);
console.log("[" + res.join(", ") + "]");
Output
[10, 12]
Time Complexity: O(k + k log k) = O(k log k), where k is the number of valid numbers generated.
Space Complexity: O(d) for recursion stack (d = maximum number of digits).