Number of ways to write N as a sum of K non-negative integers
Given two positive integers N and K, the task is to count the number of ways to write N as a sum of K non-negative integers.
Examples:
Input: N = 2, K = 3
Output: 6
Explanation:
The total ways in which 2 can be split into K non-negative integers are:
1. (0, 0, 2)
2. (0, 2, 0)
3. (2, 0, 0)
4. (0, 1, 1)
5. (1, 0, 1)
6. (1, 1, 0)
Input: N = 3, K = 2
Output: 4
Explanation:
The total ways in which can be split 3 into 2 non-negative integers are:
1. (0, 3)
2. (3, 0)
3. (1, 2)
4. (2, 1)
Approach: This problem can be solved using Dynamic Programming. Below are the steps:
- Initialize a 2D array as dp[K+1][N+1] where rows correspond to the number of the element we pick and columns correspond to the corresponding sum.
- Start filling the first row and column with taking sum as K in the above table dp[][].
- Suppose we reach at ith row and jth column, i.e i elements we can pick and we need to get sum j. To calculate the number of ways till dp[i][j] choose first (i – 1) elements and next (j – x) where x is the sum of first (i – 1) elements.
- Repeat the above steps to fill the dp[][] array.
- The value dp[n][m] will give the required result.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int countWays( int n, int m)
{
int dp[m + 1][n + 1];
for ( int i = 0; i <= n; i++) {
dp[1][i] = 1;
}
int sum;
for ( int i = 2; i <= m; i++) {
for ( int j = 0; j <= n; j++) {
sum = 0;
for ( int k = 0; k <= j; k++) {
sum += dp[i - 1][k];
}
dp[i][j] = sum;
}
}
return dp[m][n];
}
int main()
{
int N = 2, K = 3;
cout << countWays(N, K);
return 0;
}
|
Java
import java.util.*;
class GFG{
static int countWays( int n, int m)
{
int [][]dp = new int [m + 1 ][n + 1 ];
for ( int i = 0 ; i <= n; i++)
{
dp[ 1 ][i] = 1 ;
}
int sum;
for ( int i = 2 ; i <= m; i++)
{
for ( int j = 0 ; j <= n; j++)
{
sum = 0 ;
for ( int k = 0 ; k <= j; k++)
{
sum += dp[i - 1 ][k];
}
dp[i][j] = sum;
}
}
return dp[m][n];
}
public static void main(String[] args)
{
int N = 2 , K = 3 ;
System.out.print(countWays(N, K));
}
}
|
Python3
def countWays(n, m):
dp = [[ 0 for i in range (n + 1 )]
for i in range (m + 1 )]
for i in range (n + 1 ):
dp[ 1 ][i] = 1
sum = 0
for i in range ( 2 , m + 1 ):
for j in range (n + 1 ):
sum = 0
for k in range (j + 1 ):
sum + = dp[i - 1 ][k]
dp[i][j] = sum
return dp[m][n]
if __name__ = = '__main__' :
N = 2
K = 3
print (countWays(N, K))
|
C#
using System;
class GFG{
static int countWays( int n, int m)
{
int [,]dp = new int [m + 1, n + 1];
for ( int i = 0; i <= n; i++)
{
dp[1, i] = 1;
}
int sum;
for ( int i = 2; i <= m; i++)
{
for ( int j = 0; j <= n; j++)
{
sum = 0;
for ( int k = 0; k <= j; k++)
{
sum += dp[i - 1, k];
}
dp[i, j] = sum;
}
}
return dp[m, n];
}
public static void Main(String[] args)
{
int N = 2, K = 3;
Console.Write(countWays(N, K));
}
}
|
Javascript
<script>
function countWays(n, m)
{
var dp = Array.from(Array(m+1), ()=>Array(n+1));
for ( var i = 0; i <= n; i++) {
dp[1][i] = 1;
}
var sum;
for ( var i = 2; i <= m; i++) {
for ( var j = 0; j <= n; j++) {
sum = 0;
for ( var k = 0; k <= j; k++) {
sum += dp[i - 1][k];
}
dp[i][j] = sum;
}
}
return dp[m][n];
}
var N = 2, K = 3;
document.write( countWays(N, K));
</script>
|
Time Complexity: O(K*N2)
Auxiliary Space Complexity: O(N*K)
Optimized Approach: The idea of calculating the sum and then storing the count increases the time complexity. We can decrease it by storing the sum in the above dp[][] table.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int countWays( int n, int m)
{
int dp[m + 1][n + 1];
for ( int i = 0; i <= n; i++) {
dp[1][i] = 1;
if (i != 0) {
dp[1][i] += dp[1][i - 1];
}
}
for ( int i = 2; i <= m; i++) {
for ( int j = 0; j <= n; j++) {
if (j == 0) {
dp[i][j] = dp[i - 1][j];
}
else {
dp[i][j] = dp[i - 1][j];
if (i == m && j == n) {
return dp[i][j];
}
dp[i][j] += dp[i][j - 1];
}
}
}
}
int main()
{
int N = 2, K = 3;
cout << countWays(N, K);
return 0;
}
|
Java
import java.util.*;
class GFG{
static int countWays( int n, int m)
{
int [][]dp = new int [m + 1 ][n + 1 ];
for ( int i = 0 ; i <= n; i++)
{
dp[ 1 ][i] = 1 ;
if (i != 0 )
{
dp[ 1 ][i] += dp[ 1 ][i - 1 ];
}
}
for ( int i = 2 ; i <= m; i++)
{
for ( int j = 0 ; j <= n; j++)
{
if (j == 0 )
{
dp[i][j] = dp[i - 1 ][j];
}
else
{
dp[i][j] = dp[i - 1 ][j];
if (i == m && j == n)
{
return dp[i][j];
}
dp[i][j] += dp[i][j - 1 ];
}
}
}
return Integer.MIN_VALUE;
}
public static void main(String[] args)
{
int N = 2 , K = 3 ;
System.out.print(countWays(N, K));
}
}
|
Python3
def countWays(n, m):
dp = [[ 0 for i in range (n + 1 )]
for j in range (m + 1 )]
for i in range (n + 1 ):
dp[ 1 ][i] = 1
if (i ! = 0 ):
dp[ 1 ][i] + = dp[ 1 ][i - 1 ]
for i in range ( 2 , m + 1 ):
for j in range (n + 1 ):
if (j = = 0 ):
dp[i][j] = dp[i - 1 ][j]
else :
dp[i][j] = dp[i - 1 ][j]
if (i = = m and j = = n):
return dp[i][j]
dp[i][j] + = dp[i][j - 1 ]
N = 2
K = 3
print (countWays(N, K))
|
C#
using System;
class GFG{
static int countWays( int n, int m)
{
int [,]dp = new int [m + 1, n + 1];
for ( int i = 0; i <= n; i++)
{
dp[1, i] = 1;
if (i != 0)
{
dp[1, i] += dp[1, i - 1];
}
}
for ( int i = 2; i <= m; i++)
{
for ( int j = 0; j <= n; j++)
{
if (j == 0)
{
dp[i, j] = dp[i - 1, j];
}
else
{
dp[i, j] = dp[i - 1, j];
if (i == m && j == n)
{
return dp[i, j];
}
dp[i, j] += dp[i, j - 1];
}
}
}
return Int32.MinValue;
}
public static void Main()
{
int N = 2, K = 3;
Console.Write(countWays(N, K));
}
}
|
Javascript
<script>
function countWays(n,m)
{
let dp = new Array(m + 1);
for (let i=0;i<m+1;i++)
{
dp[i]= new Array(n+1);
for (let j=0;j<n+1;j++)
dp[i][j]=0;
}
for (let i = 0; i <= n; i++)
{
dp[1][i] = 1;
if (i != 0)
{
dp[1][i] += dp[1][i - 1];
}
}
for (let i = 2; i <= m; i++)
{
for (let j = 0; j <= n; j++)
{
if (j == 0)
{
dp[i][j] = dp[i - 1][j];
}
else
{
dp[i][j] = dp[i - 1][j];
if (i == m && j == n)
{
return dp[i][j];
}
dp[i][j] += dp[i][j - 1];
}
}
}
return Number.MIN_VALUE;
}
let N = 2, K = 3;
document.write(countWays(N, K));
</script>
|
Time Complexity: O(K*N)
Auxiliary Space: O(N*K)
Efficient Approach : using array instead of 2d matrix to optimize space complexity
In previous code we can se that dp[i][j] is dependent upon dp[i-1][j] or dp[i][j-1] so we can assume that dp[i-1] is previous row and dp[i] is current row.
Implementations Steps :
- Create two vectors prev and curr each of size n+1, where n is a given number.
- Initialize them with base cases.
- Now In previous code change dp[i] to curr and change dp[i-1] to prev to keep track only of the two main rows.
- After every iteration update previous row to current row to iterate further.
Implementation :
C++
#include <bits/stdc++.h>
using namespace std;
int countWays( int n, int m)
{
vector< int >prev(n+1 , 0);
vector< int >curr(n+1 , 0);
for ( int i = 0; i <= n; i++) {
prev[i] = 1;
if (i != 0) {
prev[i] += prev[i - 1];
}
}
for ( int i = 2; i <= m; i++) {
for ( int j = 0; j <= n; j++) {
if (j == 0) {
curr[j] = prev[j];
}
else {
curr[j] = prev[j];
if (i == m && j == n) {
return curr[j];
}
curr[j] += curr[j - 1];
}
}
prev = curr;
}
}
int main()
{
int N = 2, K = 3;
cout << countWays(N, K);
return 0;
}
|
Java
import java.util.*;
public class Main {
static int countWays( int n, int m) {
int [] prev = new int [n + 1 ];
int [] curr = new int [n + 1 ];
for ( int i = 0 ; i <= n; i++) {
prev[i] = 1 ;
if (i != 0 ) {
prev[i] += prev[i - 1 ];
}
}
for ( int i = 2 ; i <= m; i++) {
for ( int j = 0 ; j <= n; j++) {
if (j == 0 ) {
curr[j] = prev[j];
}
else {
curr[j] = prev[j];
if (i == m && j == n) {
return curr[j];
}
curr[j] += curr[j - 1 ];
}
}
prev = curr.clone();
}
return curr[n];
}
public static void main(String[] args) {
int N = 2 , K = 3 ;
System.out.println(countWays(N, K));
}
}
|
Python3
def countWays(n, m):
prev = [ 0 ] * (n + 1 )
curr = [ 0 ] * (n + 1 )
for i in range (n + 1 ):
prev[i] = 1
if i ! = 0 :
prev[i] + = prev[i - 1 ]
for i in range ( 2 , m + 1 ):
for j in range (n + 1 ):
if j = = 0 :
curr[j] = prev[j]
else :
curr[j] = prev[j]
if i = = m and j = = n:
return curr[j]
curr[j] + = curr[j - 1 ]
prev = curr.copy()
N = 2
K = 3
print (countWays(N, K))
|
C#
using System;
class GFG
{
static int countWays( int n, int m)
{
int [] prev = new int [n + 1];
int [] curr = new int [n + 1];
for ( int i = 0; i <= n; i++)
{
prev[i] = 1;
if (i != 0)
{
prev[i] += prev[i - 1];
}
}
for ( int i = 2; i <= m; i++)
{
for ( int j = 0; j <= n; j++)
{
if (j == 0)
{
curr[j] = prev[j];
}
else
{
curr[j] = prev[j];
if (i == m && j == n)
{
return curr[j];
}
curr[j] += curr[j - 1];
}
}
prev = curr;
}
return curr[n];
}
static void Main()
{
int N = 2, K = 3;
Console.WriteLine(countWays(N, K));
}
}
|
Javascript
function countWays(n, m) {
let prev = new Array(n + 1).fill(0);
let curr = new Array(n + 1).fill(0);
for (let i = 0; i <= n; i++) {
prev[i] = 1;
if (i != 0) {
prev[i] += prev[i - 1];
}
}
for (let i = 2; i <= m; i++) {
for (let j = 0; j <= n; j++) {
if (j == 0) {
curr[j] = prev[j];
}
else {
curr[j] = prev[j];
if (i == m && j == n) {
return curr[j];
}
curr[j] += curr[j - 1];
}
}
prev = [...curr];
}
}
let N = 2,
K = 3;
console.log(countWays(N, K));
|
Time Complexity: O(K*N)
Auxiliary Space: O(N)
Last Updated :
13 Apr, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...