Given two integers n and sum, find the number of n-digit positive integers whose digits add up to sum.
- An n-digit number cannot have leading zeros; that is, the first digit must be between 1 and 9.
- If there exist no n digit number with sum of digits equal to given sum, return -1.
Example:
Input: n = 2, sum= 2
Output: 2
Explanation: The numbers are 11 and 20 .Input: n = 1, sum = 10
Output: -1
Explanation: A single-digit number can only have a digit sum between 0 and 9.Input: n = 2, sum= 5
Output: 5
Explanation: The numbers are 14, 23, 32, 41 and 50.
Table of Content
[Naive Approach] - Recursively Try All - O(n*(9^n)) Time and O(n) Space
The idea is to use recursion to try every digit from 0 to 9 for each position, reducing the given sum at each step. The first digit is taken from 1 to 9 to ensure valid n-digit numbers. The recursion stops when there are no digits left, checking if the sumbecomes zero.
#include <iostream>
using namespace std;
// Recursive function to count n-digit numbers
// with sum of digits as the target.
int countRec(int n, int sum) {
// Base case: If there are no digits left,
// check if the target is also zero.
if (n == 0) {
return sum == 0;
}
// If the target becomes zero,
// there's exactly one valid number.
if (sum == 0) {
return 1;
}
int ans = 0;
// Traverse through digits 0-9 to calculate
// the count of numbers recursively.
for (int i = 0; i <= 9; i++) {
if (sum - i >= 0) {
ans += countRec(n - 1, sum - i);
}
}
return ans;
}
// Function to count n-digit numbers
// with sum of digits as the target.
int countWays(int n, int sum) {
int ans = 0;
// Traverse through digits 1-9 as the first
// digit cannot be zero for n-digit numbers.
for (int i = 1; i <= 9; i++) {
if (sum - i >= 0) {
ans += countRec(n - 1, sum - i);
}
}
if(ans == 0) return -1;
return ans;
}
int main() {
int n = 2;
int sum = 5;
int ans = countWays(n, sum);
cout<<ans;
return 0;
}
class GfG {
// Recursive function to count n-digit numbers
// with sum of digits as the target.
static int countRec(int n, int sum) {
// Base case: If there are no digits left,
// check if the target is also zero.
if (n == 0) {
return sum == 0 ? 1 : 0;
}
// If the target becomes zero,
// there's exactly one valid number.
if (sum == 0) {
return 1;
}
int ans = 0;
// Traverse through digits 0-9 to calculate
// the count of numbers recursively.
for (int i = 0; i <= 9; i++) {
if (sum - i >= 0) {
ans += countRec(n - 1, sum - i);
}
}
return ans;
}
// Function to count n-digit numbers
// with sum of digits as the target.
static int countWays(int n, int sum) {
int ans = 0;
// Traverse through digits 1-9 as the first
// digit cannot be zero for n-digit numbers.
for (int i = 1; i <= 9; i++) {
if (sum - i >= 0) {
ans += countRec(n - 1, sum - i);
}
}
if(ans == 0) return -1;
return ans;
}
public static void main(String[] args) {
int n = 2;
int sum = 5;
int ans = countWays(n, sum);
System.out.println(ans);
}
}
def countRec(n, sum):
# Base case: If there are no digits left,
# check if the target is also zero.
if n == 0:
return 1 if sum == 0 else 0
# If the target becomes zero,
# there's exactly one valid number.
if sum == 0:
return 1
ans = 0
# Traverse through digits 0-9 to calculate
# the count of numbers recursively.
for i in range(10):
if sum - i >= 0:
ans += countRec(n - 1, sum - i)
return ans
# Function to count n-digit numbers
# with sum of digits as the target.
def countWays(n, sum):
ans = 0
# Traverse through digits 1-9 as the first
# digit cannot be zero for n-digit numbers.
for i in range(1, 10):
if sum - i >= 0:
ans += countRec(n - 1, sum - i)
if(ans == 0):
return -1;
return ans
if __name__ == "__main__":
n = 2
sum = 5
ans = countWays(n, sum)
print(ans)
using System;
class GfG {
// Recursive function to count n-digit numbers
// with sum of digits as the target.
static int CountRec(int n, int sum) {
// Base case: If there are no digits left,
// check if the target is also zero.
if (n == 0) {
return sum == 0 ? 1 : 0;
}
// If the target becomes zero,
// there's exactly one valid number.
if (sum == 0) {
return 1;
}
int ans = 0;
// Traverse through digits 0-9 to calculate
// the count of numbers recursively.
for (int i = 0; i <= 9; i++) {
if (sum - i >= 0) {
ans += CountRec(n - 1, sum - i);
}
}
return ans;
}
// Function to count n-digit numbers
// with sum of digits as the target.
static int countWays(int n, int sum) {
int ans = 0;
// Traverse through digits 1-9 as the first
// digit cannot be zero for n-digit numbers.
for (int i = 1; i <= 9; i++) {
if (sum - i >= 0) {
ans += CountRec(n - 1, sum - i);
}
}
if(ans == 0) return -1;
return ans;
}
public static void Main(string[] args) {
int n = 2;
int sum = 5;
int ans = countWays(n, sum);
Console.WriteLine(ans);
}
}
function countRec(n, sum) {
// Base case: If there are no digits left,
// check if the target is also zero.
if (n === 0) {
return sum === 0 ? 1 : 0;
}
// If the target becomes zero,
// there's exactly one valid number.
if (sum === 0) {
return 1;
}
let ans = 0;
// Traverse through digits 0-9 to calculate
// the count of numbers recursively.
for (let i = 0; i <= 9; i++) {
if (sum - i >= 0) {
ans += countRec(n - 1, sum - i);
}
}
return ans;
}
// Function to count n-digit numbers
// with sum of digits as the target.
function countWays(n, sum) {
let ans = 0;
// Traverse through digits 1-9 as the first
// digit cannot be zero for n-digit numbers.
for (let i = 1; i <= 9; i++) {
if (sum - i >= 0) {
ans += countRec(n - 1, sum - i);
}
}
if(ans == 0) return -1;
return ans;
}
const n = 2;
const sum = 5;
const ans = countWays(n, sum);
console.log(ans);
Output
5
[Better Approach] - Memoization - O(n * sum) Time and O(n * sum) Space
The idea is to count n-digit numbers with a sum of digits equal to the given sum using recursion with memoization to optimize repeated calculations.
- A 2d array memo[][] of size (n+1)x(sum+1) is used where memo[[i][j] denotes count of i digit numbers having sum j.
- Starting from digits 1 to 9 for the first position, recursively explores all possible digits while reducing the given sum, ensuring efficiency by reusing previously computed results.
#include <iostream>
#include <vector>
using namespace std;
// Recursive function to count n-digit numbers
// with sum of digits as the target.
int countRec(int n, int sum,
vector<vector<int>> &memo) {
// Base case: If there are no digits left,
// check if the target is also zero.
if (n == 0) {
return sum == 0;
}
// If the target becomes zero,
// there's exactly one valid number.
if (sum == 0) {
return 1;
}
// Check if already computed
if (memo[n][sum] != -1) {
return memo[n][sum];
}
int ans = 0;
// Traverse through digits 0-9 to calculate
// the count of numbers recursively.
for (int i = 0; i <= 9; i++) {
if (sum - i >= 0) {
ans += countRec(n - 1,
sum - i, memo);
}
}
// Store and return the result
return memo[n][sum] = ans;
}
// Function to count n-digit numbers
// with sum of digits as the target.
int countWays(int n, int sum) {
// Create a memoization table
vector<vector<int>> memo(n + 1,
vector<int>(sum + 1, -1));
int ans = 0;
// Traverse through digits 1-9 as the first
// digit cannot be zero for n-digit numbers.
for (int i = 1; i <= 9; i++) {
if (sum - i >= 0) {
ans += countRec(n - 1, sum - i, memo);
}
}
if(ans == 0) return -1;
return ans;
}
int main() {
int n = 2;
int sum = 5;
int ans = countWays(n, sum);
cout<<ans;
return 0;
}
import java.util.Arrays;
class GfG {
// Recursive function to count n-digit numbers
// with sum of digits as the target.
static int countRec(
int n, int sum, int[][] memo) {
// Base case: If there are no digits left,
// check if the target is also zero.
if (n == 0) {
return sum == 0 ? 1 : 0;
}
// If the target becomes zero,
// there's exactly one valid number.
if (sum == 0) {
return 1;
}
// If already computed, return the result.
if (memo[n][sum] != -1) {
return memo[n][sum];
}
int ans = 0;
// Traverse through digits 0-9 to calculate
// the count of numbers recursively.
for (int i = 0; i <= 9; i++) {
if (sum - i >= 0) {
ans += countRec(
n - 1, sum - i, memo);
}
}
// Store and return the result.
return memo[n][sum] = ans;
}
// Function to count n-digit numbers
// with sum of digits as the target.
static int countWays(int n, int sum) {
// Create a memoization table.
int[][] memo = new int[n + 1]
[sum + 1];
// Initialize memo with -1 to indicate
// uncomputed states.
for (int[] row : memo) {
Arrays.fill(row, -1);
}
int ans = 0;
// Traverse through digits 1-9 as the first
// digit cannot be zero for n-digit numbers.
for (int i = 1; i <= 9; i++) {
if (sum - i >= 0) {
ans += countRec(
n - 1, sum - i, memo);
}
}
if(ans == 0) return -1;
return ans;
}
public static void main(String[] args) {
int n = 2;
int sum = 5;
int ans = countWays(n, sum);
System.out.println(ans);
}
}
def countRec(n, sum, memo):
# Base case: If there are no digits left,
# check if the target is also zero.
if n == 0:
return 1 if sum == 0 else 0
# If the target becomes zero,
# there's exactly one valid number.
if sum == 0:
return 1
# If already computed, return the result.
if memo[n][sum] != -1:
return memo[n][sum]
ans = 0
# Traverse through digits 0-9 to calculate
# the count of numbers recursively.
for i in range(10):
if sum - i >= 0:
ans += countRec(n - 1, sum - i, memo)
# Store and return the result.
memo[n][sum] = ans
return ans
# Function to count n-digit numbers
# with sum of digits as the target.
def countWays(n, sum):
# Create a memoization table initialized to -1.
memo = [[-1] * (sum + 1) for _ in range(n + 1)]
ans = 0
# Traverse through digits 1-9 as the first
# digit cannot be zero for n-digit numbers.
for i in range(1, 10):
if sum - i >= 0:
ans += countRec(n - 1, sum - i, memo)
if(ans == 0):
return -1;
return ans
if __name__ == "__main__":
n = 2
sum = 5
ans = countWays(n, sum)
print(ans)
using System;
class GfG {
static int CountRec(int n, int sum, int[,] memo) {
// Base case: If there are no digits left,
// check if the target is also zero.
if (n == 0) {
return sum == 0 ? 1 : 0;
}
// If the target becomes zero,
// there's exactly one valid number.
if (sum == 0) {
return 1;
}
// If already computed, return the result.
if (memo[n, sum] != -1) {
return memo[n, sum];
}
int ans = 0;
// Traverse through digits 0-9 to calculate
// the count of numbers recursively.
for (int i = 0; i <= 9; i++) {
if (sum - i >= 0) {
ans += CountRec(n - 1, sum - i, memo);
}
}
// Store and return the result.
memo[n, sum] = ans;
return ans;
}
// Function to count n-digit numbers
// with sum of digits as the target.
static int countWays(int n, int sum) {
// Initialize a memoization table with -1.
int[,] memo = new int[n + 1, sum + 1];
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= sum; j++) {
memo[i, j] = -1;
}
}
int ans = 0;
// Traverse through digits 1-9 as the first
// digit cannot be zero for n-digit numbers.
for (int i = 1; i <= 9; i++) {
if (sum - i >= 0) {
ans += CountRec(n - 1, sum - i, memo);
}
}
if(ans == 0) return -1;
return ans;
}
public static void Main(string[] args) {
int n = 2;
int sum = 5;
int ans = countWays(n, sum);
Console.WriteLine(ans);
}
}
function countRec(n, sum, memo) {
// Base case: If there are no digits left,
// check if the target is also zero.
if (n === 0) {
return sum === 0 ? 1 : 0;
}
// If the target becomes zero,
// there's exactly one valid number.
if (sum === 0) {
return 1;
}
// If already computed, return the result.
if (memo[n][sum] !== -1) {
return memo[n][sum];
}
let ans = 0;
// Traverse through digits 0-9 to calculate
// the count of numbers recursively.
for (let i = 0; i <= 9; i++) {
if (sum - i >= 0) {
ans += countRec(n - 1, sum - i, memo);
}
}
// Store and return the result.
memo[n][sum] = ans;
return ans;
}
// Function to count n-digit numbers
// with sum of digits as the target.
function countWays(n, sum) {
// Initialize a memoization table with -1.
const memo = Array.from({ length: n + 1 }, () =>
Array(sum + 1).fill(-1)
);
let ans = 0;
// Traverse through digits 1-9 as the first
// digit cannot be zero for n-digit numbers.
for (let i = 1; i <= 9; i++) {
if (sum - i >= 0) {
ans += countRec(n - 1, sum - i, memo);
}
}
if(ans == 0) return -1;
return ans;
}
//driver code
const n = 2;
const sum = 5;
const ans = countWays(n, sum);
console.log(ans);
Output
5
[Expected Approach] - Tabulation - O(n * sum) Time and O(n * sum) Space
The idea is to build the answer in a bottom-up manner using dynamic programming. We create a 2D DP table where dp[len][s] stores the number of ways to form a digit sequence of length len whose digits add up to s.
- We start with the base case dp[0][0] = 1, representing one way to achieve a sum of 0 using 0 digits.
- Then, for each length and sum, we consider all possible digits from 0 to 9 and use previously computed states to update the current state.
- By filling the table systematically, every subproblem is solved exactly once.
- Since the first digit of an n-digit number cannot be 0, we choose the first digit from 1 to 9 and use the DP table to count the valid ways to form the remaining digits.
#include <iostream>
#include<vector>
using namespace std;
// Function to count n-digit numbers
// with sum of digits as the target.
int countWays(int n, int sum) {
if (sum > 9 * n)
return -1;
// dp[len][s] = count of len-digit sequences
// having digit sum equal to s.
vector<vector<int>> dp(n + 1, vector<int>(sum + 1, 0));
dp[0][0] = 1;
// Build the DP table.
for (int len = 1; len <= n; len++) {
for (int s = 0; s <= sum; s++) {
for (int digit = 0; digit <= 9; digit++) {
if (s >= digit) {
dp[len][s] += dp[len - 1][s - digit];
}
}
}
}
int ans = 0;
// First digit must be from 1 to 9.
for (int digit = 1; digit <= 9; digit++) {
if (sum >= digit) {
ans += dp[n - 1][sum - digit];
}
}
return (ans == 0) ? -1 : ans;
}
int main() {
int n = 2;
int sum = 5;
int ans = countWays(n, sum);
cout<<ans;
return 0;
}
import java.util.Arrays;
class GfG {
// Function to count n-digit numbers
// with sum of digits as the target.
static int countWays(int n, int sum) {
if (sum > 9 * n) return -1;
// dp[len][s] = count of len-digit sequences
// having digit sum equal to s.
int[][] dp = new int[n + 1][sum + 1];
dp[0][0] = 1;
// Build the DP table.
for (int len = 1; len <= n; len++) {
for (int s = 0; s <= sum; s++) {
for (int digit = 0; digit <= 9; digit++) {
if (s >= digit) {
dp[len][s] += dp[len - 1][s - digit];
}
}
}
}
int ans = 0;
// First digit must be from 1 to 9.
for (int digit = 1; digit <= 9; digit++) {
if (sum >= digit) {
ans += dp[n - 1][sum - digit];
}
}
return (ans == 0) ? -1 : ans;
}
public static void main(String[] args) {
int n = 2;
int sum = 5;
int ans = countWays(n, sum);
System.out.println(ans);
}
}
# Function to count n-digit numbers
# with sum of digits as the target.
def countWays(n, sum):
if sum > 9 * n:
return -1
# dp[len][s] = count of len-digit sequences
# having digit sum equal to s.
dp = [[0] * (sum + 1) for _ in range(n + 1)]
dp[0][0] = 1
# Build the DP table.
for length in range(1, n + 1):
for s in range(sum + 1):
for digit in range(10):
if s >= digit:
dp[length][s] += dp[length - 1][s - digit]
ans = 0
# First digit must be from 1 to 9.
for digit in range(1, 10):
if sum >= digit:
ans += dp[n - 1][sum - digit]
return -1 if ans == 0 else ans
if __name__ == "__main__":
n = 2
sum = 5
print(countWays(n, sum))
using System;
class GFG
{
// Function to count n-digit numbers
// with sum of digits as the target.
static int countWays(int n, int sum)
{
if (sum > 9 * n) return -1;
// dp[len, s] = count of len-digit sequences
// having digit sum equal to s.
int[,] dp = new int[n + 1, sum + 1];
dp[0, 0] = 1;
// Build the DP table.
for (int len = 1; len <= n; len++)
{
for (int s = 0; s <= sum; s++)
{
for (int digit = 0; digit <= 9; digit++)
{
if (s >= digit)
{
dp[len, s] += dp[len - 1, s - digit];
}
}
}
}
int ans = 0;
// First digit must be from 1 to 9.
for (int digit = 1; digit <= 9; digit++)
{
if (sum >= digit)
{
ans += dp[n - 1, sum - digit];
}
}
return (ans == 0) ? -1 : ans;
}
static void Main()
{
int n = 2;
int sum = 5;
int ans = countWays(n, sum);
Console.WriteLine(ans);
}
}
function countWays(n, sum) {
if (sum > 9 * n) return -1;
// dp[len][s] = count of len-digit sequences
// having digit sum equal to s.
let dp = Array.from({ length: n + 1 }, () => Array(sum + 1).fill(0));
dp[0][0] = 1;
// Build the DP table.
for (let len = 1; len <= n; len++) {
for (let s = 0; s <= sum; s++) {
for (let digit = 0; digit <= 9; digit++) {
if (s >= digit) {
dp[len][s] += dp[len - 1][s - digit];
}
}
}
}
let ans = 0;
// First digit must be from 1 to 9.
for (let digit = 1; digit <= 9; digit++) {
if (sum >= digit) {
ans += dp[n - 1][sum - digit];
}
}
return ans == 0 ? -1 : ans;
}
// Driver code
let n = 2;
let sum = 5;
console.log(countWays(n, sum));
Output
5