Open In App

Count of ways to split a given number

Improve
Improve
Like Article
Like
Save
Share
Report

Given a number N, the task is to find the count of unique ways to split it into different parts.

Note: {2, 1} and {1, 2} will be considered as one way.

Examples:

Input: n = 5
Output: 7
Explanation: There are 7 ways to split 5:
5
4 + 1
3 + 2
3 + 1 + 1
2 + 2 + 1
2 + 1 + 1 + 1
1 + 1 + 1 + 1 + 1

Input: n = 3
Output: 3
Explanation: There are 3 ways to split 3:
3
2 + 1
1 + 1 + 1

Count of ways to split a given number using Recursion:

Recurrence Relation:

findWays(remainingSum, currentNumber) = findWays(remainingSum – currentNumber, currentNumber) + findWays(remainingSum, currentNumber + 1)

Approach: To solve the problem follow the below idea:

To count all the ways to split a given number remainingSum into smaller numbers, then for each smaller number currentNumber we have two choices:

  • Split remainingSum by subtracting currentNumber: Subtract the current number X from N and call the findWays function recursively with the updated remainingSum and the same currentNumber i.e., findWays(remainingSum – currentNumber, currentNumber)
  • Exclude the currentNumber: Call the findWays function recursively with the same remainingSum and the greater currentNumber. i.e., findWays(remainingSum, currentNumber + 1).

Step-by-step algorithm:

  • Maintain a recursive function, say findWays(remainingSum, currentNumber) to find the number of ways to split remainingSum into parts of size >= currentNumber.
  • In each recursuve call, there are two choices:
    • Do not break the remainingSum in a part of size = currentNumber and choose to break in a bigger part by calling findWays(remainingSum, currentNumber + 1)
    • Break the remainingSum in a part of size = currentNumber and again call findWays(remainingSum – currentNumber, currentNumber)
  • If at any recursive call, the remainingSum becomes negative then it means that the number cannot split any further, so return 0.
  • If at any recursive call, the remainingSum becomes 0, then it means that the number has already been split, so return 1.
  • After all the recursive calls, return the final answer.

Below is the implementation of the algorithm:

C++
#include <iostream>
using namespace std;

// recursive function to find the number of ways to split a
// number
int findWays(int remainingSum, int currentNumber)
{
    if (remainingSum == 0)
        return 1;
    if (remainingSum < 0 || currentNumber > remainingSum)
        return 0;
    // Skip the current number
    int ways1 = findWays(remainingSum, currentNumber + 1);
    // Choose the current number
    int ways2 = findWays(remainingSum - currentNumber,
                         currentNumber);
    return ways1 + ways2;
}

// function to find the number of ways to split a number
int solve(int n)
{
    if (n <= 0)
        return 0;
    return findWays(n, 1);
}

int main()
{
      // function call
      int n = 5;
    cout << solve(n) << "\n";
    return 0;
}

Output
7

Time Complexity: O(2^n)
Auxiliary Space: O(n)

Count of ways to split a given number using Dynamic Programming (Memoization):

Algorithm: To solve the problem, follow the below idea:

We can observe that the above recursive approach has Overlapping Subproblems and Optimal Substructure so we can optimize it by storing the already computed results using Memoization. So, now we can use a dp[][] array of size N X N, such that dp[i][j] stores the number of ways to split number i into parts such that each part >= j.

Below is the implementation of the algorithm:

C++
#include <bits/stdc++.h>
using namespace std;

// recursive function to find the number of ways to split a
// number
int findWays(int remainingSum, int currentNumber, vector<vector<int>> &dp)
{
    if (remainingSum == 0)
        return 1;
    if (remainingSum < 0 || currentNumber > remainingSum)
        return 0;
      if(dp[remainingSum][currentNumber] != -1)
      return dp[remainingSum][currentNumber];
    // Skip the current number
    int ways1 = findWays(remainingSum, currentNumber + 1, dp);
    // Choose the current number
    int ways2 = findWays(remainingSum - currentNumber,
                         currentNumber, dp);
    return dp[remainingSum][currentNumber] = ways1 + ways2;
}

// function to find the number of ways to split a number
int solve(int n)
{
    if (n <= 0)
        return 0;
      vector<vector<int>> dp(n + 1, vector<int>(n + 1, -1));
    return findWays(n, 1, dp);
}

int main()
{
      // function call
    cout << solve(5) << "\n";
    return 0;
}

Output
7

Time Complexity: O(n^2)
Auxiliary Space: O(n)



Last Updated : 19 Mar, 2024
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads