Dynamic ProgrammingNumber of Longest Increasing Subsequences

Number of Longest Increasing Subsequences

16 mins read The Jat Medium Updated 11 months ago
Dynamic Programming

Problem Statement

Given an integer array nums, find the number of Longest Increasing Subsequences (LIS) in the array.

Examples

Example 1:

Input: nums = [1, 3, 5, 4, 7]
Output: 2

Explanation: There are two LIS of length 4:
[1, 3, 4, 7]
[1, 3, 5, 7]
Example 2:

Input: nums = [2, 2, 2, 2, 2]
Output: 5

Explanation: All elements are the same, so every single element can form an LIS of length 1. There are 5 such subsequences.

Different Approaches

1️⃣ Recursion (TLE)

Intuition:

Try every subsequence using recursion. Track:

  • Max length of LIS found so far
  • Count of how many LIS match that length

Code:

class Solution {
public:
    int count = 0;  // To count how many LIS of maximum length exist
    int maxi = 0;   // To track the length of the Longest Increasing Subsequence (LIS)

    // Recursive DFS to explore all possible increasing subsequences
    void dfs(int index, vector<int>& nums, vector<int>& path) {
        // Base case: if we've reached the end of the array
        if (index == nums.size()) {
            // If current path is longer than previous maximum, update max and reset count
            if (path.size() > maxi) {
                maxi = path.size();
                count = 1;
            }
            // If it's equal to max length, increment the count
            else if (path.size() == maxi) {
                count++;
            }
            return;
        }

        // ✅ CHOICE 1: Include the current element if it forms an increasing subsequence
        // (i.e., it's larger than the last element in the current path)
        if (path.empty() || nums[index] > path.back()) {
            path.push_back(nums[index]);     // include current element
            dfs(index + 1, nums, path);      // explore further with it included
            path.pop_back();                 // backtrack (remove the element after exploring)
        }

        // ✅ CHOICE 2: Exclude the current element and move to next index
        dfs(index + 1, nums, path);
    }

    // Entry point: initializes DFS
    int numberOfLIS(vector<int> nums) {
        vector<int> path;       // Holds the current subsequence
        dfs(0, nums, path);     // Start DFS from index 0
        return count;           // Return total count of longest increasing subsequences
    }
};

Complexity Analysis:

  • Time Complexity: O(2^n)
  • Space Complexity: O(n)
    • Stack Space

2️⃣ Tabulation (Bottom-Up Approach)

Code:

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

class Solution {
public:
    /* Function to count the number of LIS 
    present in the given array */
    int numberOfLIS(vector<int> nums) {
        int n = nums.size(); // Size of the array 

        int ans = 0; // To store the result
        int maxLen = 0; // To store the length of longest LIS

        vector<int> dp(n, 1); // DP table
        vector<int> count(n, 1); // To store the count

        // Filling up the DP table
        for(int ind = 0; ind < n; ind++) {
            for(int prevInd = 0; prevInd < ind; prevInd++) {

                /* If the element at index i can be
                included in the LIS ending at index j */
                if(nums[prevInd] < nums[ind]) {

                    // If a longer LIS is found, update the values
                    if(dp[prevInd] + 1 > dp[ind]) {
                        dp[ind] = dp[prevInd] + 1;
                        count[ind] = count[prevInd];
                    }

                    // Else if a new way is found to form the LIS
                    else if(dp[prevInd] + 1 == dp[ind]) {
                        count[ind] += count[prevInd];
                    }

                }
            }

            // Store the maximum length
            maxLen = max(maxLen, dp[ind]);
        }

        // Traverse the count array 
        for(int i = 0; i < n; i++) {
            // Count the longest LIS
            if(dp[i] == maxLen) ans += count[i];
        }

        return ans; // Return the result
    }
};


int main() {
    vector<int> arr = {1, 3, 5, 4, 7};
    
    /* Creating an instance of 
    Solution class */
    Solution sol; 
    
    /* Function call to count the number 
    of LIS present in given array */
    int ans = sol.numberOfLIS(arr);
    
    // Output
    cout << "The number of LIS present in the given array is: " << ans << endl;
    
    return 0;
}

Complexity Analysis:

  • Time Complexity:O(N^2), where N is the size of the given array.
    • Computing the DP array takes O(N^2) time, and counting the longest LIS present takes O(N) time.
  • Space Complexity:O(N), because of two arrays (dp and count) used, each of size N.
Buy Me A Coffee

Leave a comment

Your email address will not be published. Required fields are marked *

Your experience on this site will be improved by allowing cookies Cookie Policy