Open In App

Count of different ways to express N as the sum of 1, 3 and 4

Last Updated : 03 Dec, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

Given a positive integer n, the task is to count the number of ways to express as a sum of 1, 3 and 4.

Examples: 

Input: n = 4
Output: 4
Explanation: There is 4 ways to represent 4 as sum of 1, 3 and 4: (1+1+1+1), (1+3), (3+1) and (4).

Input: n = 3
Output: 2
Explanation: There is 2 ways to represent 3 as sum of 1, 3 and 4: (1+1+1) and (3).

Using Recursion - O(3^n) Time and O(n) Space

The idea is to recursively explore the possibilities of including 1, 3, or 4 in the sum. For any n, the result can be computed as the sum of ways for n-1, n-3 and n-4.

Mathematically the recurrence relation will look like the following:

countWays(n) = countWays(n-1) + countWays(n-3) + countWays(n-4).

Base Cases:

  • countWays(n) = 0, if n < 0.
  • countWays(n) = 1, if n == 0.
C++
// C++ Program to count the number of ways
// to express N as the sum of 1, 3, and 4
// using recursion
#include <iostream>
using namespace std;

int countWays(int n) {
    
    // Base cases
    if (n == 0) return 1;
    if (n < 0) return 0;
    
    // Recursive cases
    return countWays(n - 1) + 
           countWays(n - 3) + 
           countWays(n - 4);
}

int main() {
    int n = 5;
    cout << countWays(n);
    return 0;
}
Java
// Java Program to count the number of ways
// to express N as the sum of 1, 3, and 4
// using recursion

class GfG {

    static int countWays(int n) {

        // Base cases
        if (n == 0) return 1;
        if (n < 0) return 0;

        // Recursive cases
        return countWays(n - 1) + 
               countWays(n - 3) + 
               countWays(n - 4);
    }

    public static void main(String[] args) {
        int n = 5;
        System.out.println(countWays(n));
    }
}
Python
# Python Program to count the number of ways
# to express N as the sum of 1, 3, and 4
# using recursion

def countWays(n):
  
    # Base cases
    if n == 0:
        return 1
    if n < 0:
        return 0

    # Recursive cases
    return countWays(n - 1) + countWays(n - 3) + countWays(n - 4)

if __name__ == "__main__":
    n = 5
    print(countWays(n))
C#
// C# Program to count the number of ways
// to express N as the sum of 1, 3, and 4
// using recursion

using System;

class GfG {

    static int countWays(int n) {

        // Base cases
        if (n == 0) return 1;
        if (n < 0) return 0;

        // Recursive cases
        return countWays(n - 1) + 
               countWays(n - 3) + 
               countWays(n - 4);
    }

    static void Main(string[] args) {
        int n = 5;
        Console.WriteLine(countWays(n));
    }
}
JavaScript
// JavaScript Program to count the number of ways
// to express N as the sum of 1, 3, and 4
// using recursion

function countWays(n) {

    // Base cases
    if (n === 0) return 1;
    if (n < 0) return 0;

    // Recursive cases
    return countWays(n - 1) + 
           countWays(n - 3) + 
           countWays(n - 4);
}

let n = 5;
console.log(countWays(n));

Output
6

Using Top-Down DP (Memoization) - O(n) Time and O(n) Space

If we notice carefully, we can observe that the above recursive solution holds the following two properties of Dynamic Programming:

1. Optimal Substructure: Number of ways to make sum n, i.e., countWays(n), depends on the optimal solutions of the subproblems countWays(n-1), countWays(n-3) and countWays(n-4). By combining these optimal substructures, we can efficiently calculate the number of ways to make sum n.

2. Overlapping Subproblems: While applying a recursive approach in this problem, we notice that certain subproblems are computed multiple times.

  • There is only one parameter: n that changes in the recursive solution. So we create a 1D array of size n for memoization.
  • We initialize this array as -1 to indicate nothing is computed initially.
  • Now we modify our recursive solution to first check if the value is -1, then only make recursive calls. This way, we avoid re-computations of the same subproblems.
C++
// C++ Program to count the number of ways
// to express N as the sum of 1, 3, and 4
// using memoization
#include <bits/stdc++.h>
using namespace std;

int countRecur(int n, vector<int> &memo) {
    
    // Base cases
    if (n == 0) return 1;
    if (n < 0) return 0;
    
    // If value is memoized
    if (memo[n]!=-1) return memo[n];
    
    // Recursive cases
    return memo[n] =
        countRecur(n - 1, memo) + 
        countRecur(n - 3, memo) + 
        countRecur(n - 4, memo);
}

int countWays(int n) {
    vector<int> memo(n+1, -1);
    return countRecur(n, memo);
}

int main() {
    int n = 5;
    cout << countWays(n);
    return 0;
}
Java
// Java Program to count the number of ways
// to express N as the sum of 1, 3, and 4
// using memoization

import java.util.Arrays;

class GfG {

    static int countRecur(int n, int[] memo) {

        // Base cases
        if (n == 0) return 1;
        if (n < 0) return 0;

        // If value is memoized
        if (memo[n] != -1) return memo[n];

        // Recursive cases
        return memo[n] = countRecur(n - 1, memo) +
                         countRecur(n - 3, memo) +
                         countRecur(n - 4, memo);
    }

    static int countWays(int n) {
        int[] memo = new int[n + 1];
        Arrays.fill(memo, -1);
        return countRecur(n, memo);
    }

    public static void main(String[] args) {
        int n = 5;
        System.out.println(countWays(n));
    }
}
Python
# Python Program to count the number of ways
# to express N as the sum of 1, 3, and 4
# using memoization

def countRecur(n, memo):
  
    # Base cases
    if n == 0:
        return 1
    if n < 0:
        return 0

    # If value is memoized
    if memo[n] != -1:
        return memo[n]

    # Recursive cases
    memo[n] = countRecur(n - 1, memo) + \
    countRecur(n - 3, memo) + countRecur(n - 4, memo)
    return memo[n]

def countWays(n):
    memo = [-1] * (n + 1)
    return countRecur(n, memo)

if __name__ == "__main__":
    n = 5
    print(countWays(n))
C#
// C# Program to count the number of ways
// to express N as the sum of 1, 3, and 4
// using memoization

using System;

class GfG {

    static int countRecur(int n, int[] memo) {

        // Base cases
        if (n == 0) return 1;
        if (n < 0) return 0;

        // If value is memoized
        if (memo[n] != -1) return memo[n];

        // Recursive cases
        return memo[n] = countRecur(n - 1, memo) +
                         countRecur(n - 3, memo) +
                         countRecur(n - 4, memo);
    }

    static int countWays(int n) {
        int[] memo = new int[n + 1];
        Array.Fill(memo, -1);
        return countRecur(n, memo);
    }

    static void Main(string[] args) {
        int n = 5;
        Console.WriteLine(countWays(n));
    }
}
JavaScript
// JavaScript Program to count the number of ways
// to express N as the sum of 1, 3, and 4
// using memoization

function countRecur(n, memo) {

    // Base cases
    if (n === 0) return 1;
    if (n < 0) return 0;

    // If value is memoized
    if (memo[n] !== -1) return memo[n];

    // Recursive cases
    return memo[n] = countRecur(n - 1, memo) +
                     countRecur(n - 3, memo) +
                     countRecur(n - 4, memo);
}

function countWays(n) {
    const memo = Array(n + 1).fill(-1);
    return countRecur(n, memo);
}

const n = 5;
console.log(countWays(n));

Output
6

Using Bottom-Up DP (Tabulation) - O(n) Time and O(n) Space

The idea is to fill the DP table based on previous values. For each n, its value is dependent on n-1, n-3 and n-4. The table is filled in an iterative manner from i = 1 to i = n.

The dynamic programming relation is as follows: 

  • dp[i] = sum(dp[i-j]) for value of j = {1, 3, 4} and i-j >=0.
C++
// C++ Program to count the number of ways
// to express N as the sum of 1, 3, and 4
// using tabulation
#include <bits/stdc++.h>
using namespace std;

int countWays(int n) {
    vector<int> dp(n + 1, 0);
    dp[0] = 1;

    for (int i = 1; i <= n; i++) {

        // Calculate dp[i].
        if (i - 1 >= 0)
            dp[i] += dp[i - 1];
        if (i - 3 >= 0)
            dp[i] += dp[i - 3];
        if (i - 4 >= 0)
            dp[i] += dp[i - 4];
    }

    return dp[n];
}

int main() {
  
    int n = 5;
    cout << countWays(n);
    return 0;
}
Java
// Java Program to count the number of ways
// to express N as the sum of 1, 3, and 4
// using tabulation

class GfG {

    static int countWays(int n) {
        int[] dp = new int[n + 1];
        dp[0] = 1;

        for (int i = 1; i <= n; i++) {

            // Calculate dp[i].
            if (i - 1 >= 0) dp[i] += dp[i - 1];
            if (i - 3 >= 0) dp[i] += dp[i - 3];
            if (i - 4 >= 0) dp[i] += dp[i - 4];
        }

        return dp[n];
    }

    public static void main(String[] args) {
        int n = 5;
        System.out.println(countWays(n));
    }
}
Python
# Python Program to count the number of ways
# to express N as the sum of 1, 3, and 4
# using tabulation

def countWays(n):
    dp = [0] * (n + 1)
    dp[0] = 1

    for i in range(1, n + 1):

        # Calculate dp[i].
        if i - 1 >= 0:
            dp[i] += dp[i - 1]
        if i - 3 >= 0:
            dp[i] += dp[i - 3]
        if i - 4 >= 0:
            dp[i] += dp[i - 4]

    return dp[n]

if __name__ == "__main__":
    n = 5
    print(countWays(n))
C#
// C# Program to count the number of ways
// to express N as the sum of 1, 3, and 4
// using tabulation

using System;

class GfG {

    static int countWays(int n) {
        int[] dp = new int[n + 1];
        dp[0] = 1;

        for (int i = 1; i <= n; i++) {

            // Calculate dp[i].
            if (i - 1 >= 0) dp[i] += dp[i - 1];
            if (i - 3 >= 0) dp[i] += dp[i - 3];
            if (i - 4 >= 0) dp[i] += dp[i - 4];
        }

        return dp[n];
    }

    static void Main(string[] args) {
        int n = 5;
        Console.WriteLine(countWays(n));
    }
}
JavaScript
// JavaScript Program to count the number of ways
// to express N as the sum of 1, 3, and 44
// using tabulation

function countWays(n) {
    const dp = Array(n + 1).fill(0);
    dp[0] = 1;

    for (let i = 1; i <= n; i++) {

        // Calculate dp[i].
        if (i - 1 >= 0) dp[i] += dp[i - 1];
        if (i - 3 >= 0) dp[i] += dp[i - 3];
        if (i - 4 >= 0) dp[i] += dp[i - 4];
    }

    return dp[n];
}

const n = 5;
console.log(countWays(n));

Output
6

Using Space Optimized DP - O(n) Time and O(1) Space

In previous approach of dynamic programming we have derive the relation between states as given below:

  • dp[i] = sum(dp[i-j]) for value of j = {1, 3, 4} and i - j >=0.

If we observe that for calculating current dp[i] state we only need previous 4 states of dp. There is no need to store all the previous states.

C++
// C++ Program to count the number of ways
// to express N as the sum of 1, 3, and 4
// using space optimised dp
#include <bits/stdc++.h>
using namespace std;

int countWays(int n) {
    
    // Return values for 1st 
    // 4 states
    if (n==1) return 1;
    if (n==2) return 1;
    if (n==3) return 2;
    if (n==4) return 4;
    
    vector<int> dp(4);
    dp[0] = 1;
    dp[1] = 1;
    dp[2] = 2;
    dp[3] = 4;
    
    for (int i=5; i<=n; i++) {
        
        int curr = dp[0]+dp[1]+dp[3];
        
        // Update values
        dp[0] = dp[1];
        dp[1] = dp[2];
        dp[2] = dp[3];
        dp[3] = curr;
    }
    
    return dp[3];
}

int main() {
    int n = 5;
    cout << countWays(n);
    return 0;
}
Java
// Java Program to count the number of ways
// to express N as the sum of 1, 3, and 4
// using space optimised dp

class GfG {

    static int countWays(int n) {
        
        // Return values for 1st 
        // 4 states
        if (n == 1) return 1;
        if (n == 2) return 1;
        if (n == 3) return 2;
        if (n == 4) return 4;
        
        int[] dp = new int[4];
        dp[0] = 1;
        dp[1] = 1;
        dp[2] = 2;
        dp[3] = 4;

        for (int i = 5; i <= n; i++) {

            int curr = dp[0] + dp[1] + dp[3];

            // Update values
            dp[0] = dp[1];
            dp[1] = dp[2];
            dp[2] = dp[3];
            dp[3] = curr;
        }

        return dp[3];
    }

    public static void main(String[] args) {
        int n = 5;
        System.out.println(countWays(n));
    }
}
Python
# Python Program to count the number of ways
# to express N as the sum of 1, 3, and 4
# using space optimised dp
def countWays(n):
    
    # Return values for 1st 
    # 4 states
    if n == 1:
        return 1
    if n == 2:
        return 1
    if n == 3:
        return 2
    if n == 4:
        return 4

    dp = [1, 1, 2, 4]

    for i in range(5, n + 1):

        curr = dp[0] + dp[1] + dp[3]

        # Update values
        dp[0] = dp[1]
        dp[1] = dp[2]
        dp[2] = dp[3]
        dp[3] = curr

    return dp[3]

if __name__ == "__main__":
    n = 5
    print(countWays(n))
C#
// C# Program to count the number of ways
// to express N as the sum of 1, 3, and 4
// using space optimised dp

using System;

class GfG {

    static int countWays(int n) {
        
        // Return values for 1st 
        // 4 states
        if (n == 1) return 1;
        if (n == 2) return 1;
        if (n == 3) return 2;
        if (n == 4) return 4;

        int[] dp = new int[4];
        dp[0] = 1;
        dp[1] = 1;
        dp[2] = 2;
        dp[3] = 4;

        for (int i = 5; i <= n; i++) {

            int curr = dp[0] + dp[1] + dp[3];

            // Update values
            dp[0] = dp[1];
            dp[1] = dp[2];
            dp[2] = dp[3];
            dp[3] = curr;
        }

        return dp[3];
    }

    static void Main(string[] args) {
        int n = 5;
        Console.WriteLine(countWays(n));
    }
}
JavaScript
// JavaScript Program to count the number of ways
// to express N as the sum of 1, 3, and 4
// using space optimised dp

function countWays(n) {

    // Return values for 1st 
    // 4 states
    if (n === 1) return 1;
    if (n === 2) return 1;
    if (n === 3) return 2;
    if (n === 4) return 4;

    const dp = [1, 1, 2, 4];

    for (let i = 5; i <= n; i++) {

        const curr = dp[0] + dp[1] + dp[3];

        // Update values
        dp[0] = dp[1];
        dp[1] = dp[2];
        dp[2] = dp[3];
        dp[3] = curr;
    }

    return dp[3];
}

const n = 5;
console.log(countWays(n));

Output
6

Similar Reads