Maximum Sum Increasing Subsequence of length k

Last Updated : 16 May, 2026

Given an array, find the maximum possible sum of non-decreasing subsequence of length k. If not possible return -1.

Examples:

Input : a = {8, 5, 9, 10, 5, 6, 21, 8}, k = 3 
Output : 40 
Explanation: Possible Increasing subsequence of Length 3 with maximum possible sum is 9 + 10 + 21 = 40

Input : a = {10, 5}, k = 2
Output : -1
Explanation : Can't make any increasing subsequence of length 2.

Try It Yourself
redirect icon

Note: This problem is a simple variation of Longest Increasing Subsequence. If you are unknown of how to calculate the longest increasing subsequence then see the implementation going to the link.

[Naive Approach] Using Recursion : O(2 ^ n) Time and O(n) Space

The intuition of this code is to generate all possible subsequences using recursion and choose the one having maximum sum with exactly k elements. At every index, we have two choices: either take the current element or skip it. An element is taken only if it keeps the subsequence non-decreasing (current element >= previous selected element). Finally, among all valid subsequences of size k, we return the maximum possible sum.

  • Start recursion from index 0 with no previous element selected and required subsequence size k.
  • At each index, either take the current element if it maintains non-decreasing order, or skip the current element.
  • If exactly k elements are selected, return 0 as a valid subsequence is formed.
  • If the array ends before selecting k elements, return negative infinity (INT_MIN).
  • Return the maximum sum obtained from both choices (take and not take).
C++
#include <bits/stdc++.h>
using namespace std;

long long solve(int i, int prev, int k, int n, vector<int> &nums)
{
    // Base Case:
    // If we have selected exactly k elements
    if (k == 0)
    {
        return 0;
    }

    // If array ends before selecting k elements
    if (i == n)
    {
        return INT_MIN;
    }

    // Option 1: Take current element
    long long take = INT_MIN;

    // Current element can be taken if:
    // 1. No previous element selected
    // 2. Current element is >= previous element
    if (prev == -1 || nums[i] >= prev)
    {
        long long next = solve(i + 1, nums[i], k - 1, n, nums);

        // Add current value only if next state is valid
        if (next != INT_MIN)
        {
            take = nums[i] + next;
        }
    }

    // Option 2: Skip current element
    long long not_take = solve(i + 1, prev, k, n, nums);

    // Return maximum of both choices
    return max(take, not_take);
}

int maxSum(vector<int> &a, int k)
{
    int n = a.size();
    long long ans = solve(0, -1, k, n, a);

    // If no valid subsequence exists
    return (ans < 0) ? -1 : ans;
}

int main()
{
    vector<int> a = {8, 5, 9, 10, 5, 6, 21, 8};
    int k = 3;

    // Function call
    int result = maxSum(a, k);

    // Output result
    cout << result << endl;

    return 0;
}
Java
import java.util.*;

public class GFG {

    static long solve(int i, int prev, int k, int n,
                      int[] nums)
    {
        // Base Case:
        // If we have selected exactly k elements
        if (k == 0) {
            return 0;
        }

        // If array ends before selecting k elements
        if (i == n) {
            return Integer.MIN_VALUE;
        }

        // Option 1: Take current element
        long take = Integer.MIN_VALUE;

        // Current element can be taken if:
        // 1. No previous element selected
        // 2. Current element is >= previous element
        if (prev == -1 || nums[i] >= prev) {

            long next
                = solve(i + 1, nums[i], k - 1, n, nums);

            // Add current value only if next state is valid
            if (next != Integer.MIN_VALUE) {
                take = nums[i] + next;
            }
        }

        // Option 2: Skip current element
        long notTake = solve(i + 1, prev, k, n, nums);

        // Return maximum of both choices
        return Math.max(take, notTake);
    }

    static int maxSum(int[] a, int k)
    {
        int n = a.length;
        long ans = solve(0, -1, k, n, a);

        // If no valid subsequence exists
        return (ans < 0) ? -1 : (int)ans;
    }

    public static void main(String[] args)
    {
        int[] a = { 8, 5, 9, 10, 5, 6, 21, 8 };
        int k = 3;

        // Function call
        int result = maxSum(a, k);

        // Output result
        System.out.println(result);
    }
}
Python
import sys

def solve(i, prev, k, n, nums):

    # Base Case:
    # If we have selected exactly k elements
    if k == 0:
        return 0

    # If array ends before selecting k elements
    if i == n:
        return -sys.maxsize

    # Option 1: Take current element
    take = -sys.maxsize

    # Current element can be taken if:
    # 1. No previous element selected
    # 2. Current element is >= previous element
    if prev == -1 or nums[i] >= prev:

        next_value = solve(i + 1, nums[i], k - 1, n, nums)

        # Add current value only if next state is valid
        if next_value != -sys.maxsize:
            take = nums[i] + next_value

    # Option 2: Skip current element
    not_take = solve(i + 1, prev, k, n, nums)

    # Return maximum of both choices
    return max(take, not_take)


def maxSum(a, k):

    n = len(a)
    ans = solve(0, -1, k, n, a)

    # If no valid subsequence exists
    return -1 if ans < 0 else ans


# Driver Code
if __name__ == "__main__":
    a = [8, 5, 9, 10, 5, 6, 21, 8]
    k = 3

    # Function call
    result = maxSum(a, k)

    # Output result
    print(result)
C#
using System;

class GFG {

    static long solve(int i, int prev, int k, int n, int[] nums)
    {
        // Base Case:
        // If we have selected exactly k elements
        if (k == 0) {
            return 0;
        }

        // If array ends before selecting k elements
        if (i == n) {
            return int.MinValue;
        }

        // Option 1: Take current element
        long take = int.MinValue;

        // Current element can be taken if:
        // 1. No previous element selected
        // 2. Current element is >= previous element
        if (prev == -1 || nums[i] >= prev) {

            long next =
                solve(i + 1, nums[i], k - 1, n, nums);

            // Add current value only if next state is valid
            if (next != int.MinValue) {
                take = nums[i] + next;
            }
        }

        // Option 2: Skip current element
        long notTake = solve(i + 1, prev, k, n, nums);

        // Return maximum of both choices
        return Math.Max(take, notTake);
    }

    static int maxSum(int[] arr, int k)
    {
        int n = arr.Length;

        long ans = solve(0, -1, k, n, arr);

        // If no valid subsequence exists
        return (ans < 0) ? -1 : (int)ans;
    }

    static void Main()
    {
        // Creating array
        int[] arr = { 8, 5, 9, 10, 5, 6, 21, 8 };

        int k = 3;

        // Function call
        int result = maxSum(arr, k);

        // Output result
        Console.WriteLine(result);
    }
}
JavaScript
function solve(i, prev, k, n, nums)
{
    // Base Case:
    // If we have selected exactly k elements
    if (k === 0) {
        return 0;
    }

    // If array ends before selecting k elements
    if (i === n) {
        return Number.MIN_SAFE_INTEGER;
    }

    // Option 1: Take current element
    let take = Number.MIN_SAFE_INTEGER;

    // Current element can be taken if:
    // 1. No previous element selected
    // 2. Current element is >= previous element
    if (prev === -1 || nums[i] >= prev) {

        let next = solve(i + 1, nums[i], k - 1, n, nums);

        // Add current value only if next state is valid
        if (next !== Number.MIN_SAFE_INTEGER) {
            take = nums[i] + next;
        }
    }

    // Option 2: Skip current element
    let notTake = solve(i + 1, prev, k, n, nums);

    // Return maximum of both choices
    return Math.max(take, notTake);
}

function maxSum(a, k)
{
    let n = a.length;
    let ans = solve(0, -1, k, n, a);

    // If no valid subsequence exists
    return (ans < 0) ? -1 : ans;
}

// Driver Code
let a = [ 8, 5, 9, 10, 5, 6, 21, 8 ];
let k = 3;

// Function call
let result = maxSum(a, k);

// Output result
console.log(result);

Output
40
solve_0_1_2_i_i_0_previndex_1_k_22
Explanation using recursive tree(highlighted states showing overlapping subproblems)

[Expected Approach] Using Memoization(DP) - O(n ^ 2 * k) Time and O(n * k) Space

The main intuition behind this approach is that for every index we have only two choices: either include the current element in the subsequence or skip it. While making these choices recursively, many states get recomputed multiple times, which makes the recursive solution exponential. Since, we have repeating and overlapping subproblems, we can use Memoization(DP) thus, reducing the time complexity from exponential to polynomial.

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

long long solve(int i, int prev, int k, int n, vector<int> &nums, vector<vector<vector<long long>>> &dp)
{
    // Base Case:
    // If exactly k elements are selected
    if (k == 0)
    {
        return 0;
    }

    // If array ends before selecting k elements
    if (i == n)
    {
        return INT_MIN;
    }

    // If already computed
    if (dp[i][prev + 1][k] != -1)
    {
        return dp[i][prev + 1][k];
    }

    // Option 1: Do not take current element
    long long not_take = solve(i + 1, prev, k, n, nums, dp);

    // Option 2: Take current element
    long long take = INT_MIN;

    // Current element can be selected if:
    // 1. No previous element selected
    // 2. nums[i] >= previous selected value
    if (prev == -1 || nums[i] >= nums[prev])
    {
        long long next = solve(i + 1, i, k - 1, n, nums, dp);

        // Add current value only if next state is valid
        if (next != INT_MIN)
        {
            take = nums[i] + next;
        }
    }

    // Store and return answer
    return dp[i][prev + 1][k] = max(take, not_take);
}

int maxSum(vector<int> &a, int k)
{
    int n = a.size();

    vector<vector<vector<long long>>> dp(n, vector<vector<long long>>(n + 1, vector<long long>(k + 1, -1)));

    long long ans = solve(0, -1, k, n, a, dp);

    // If no valid subsequence exists
    return (ans < 0) ? -1 : ans;
}

int main()
{
    vector<int> arr = {8, 5, 9, 10, 5, 6, 21, 8};
    int k = 3;

    // Function call
    int result = maxSum(arr, k);

    // Output result
    cout << result << endl;

    return 0;
}
Java
import java.util.*;

public class GFG {

    static long solve(int i, int prev, int k, int n,
                      int[] nums, long[][][] dp)
    {
        // Base Case:
        // If exactly k elements are selected
        if (k == 0) {
            return 0;
        }

        // If array ends before selecting k elements
        if (i == n) {
            return Integer.MIN_VALUE;
        }

        // If already computed
        if (dp[i][prev + 1][k] != -1) {
            return dp[i][prev + 1][k];
        }

        // Option 1: Do not take current element
        long notTake
            = solve(i + 1, prev, k, n, nums, dp);

        // Option 2: Take current element
        long take = Integer.MIN_VALUE;

        // Current element can be selected if:
        // 1. No previous element selected
        // 2. nums[i] >= previous selected value
        if (prev == -1 || nums[i] >= nums[prev]) {

            long next = solve(i + 1, i, k - 1, n, nums, dp);

            // Add current value only if next state is valid
            if (next != Integer.MIN_VALUE) {
                take = nums[i] + next;
            }
        }

        // Store and return answer
        return dp[i][prev + 1][k]
            = Math.max(take, notTake);
    }

    static int maxSum(int[] a, int k)
    {
        int n = a.length;

        long[][][] dp = new long[n][n + 1][k + 1];

        // Initialize DP array with -1
        for (int i = 0; i < n; i++) {
            for (int j = 0; j <= n; j++) {
                Arrays.fill(dp[i][j], -1);
            }
        }

        long ans = solve(0, -1, k, n, a, dp);

        // If no valid subsequence exists
        return (ans < 0) ? -1 : (int)ans;
    }

    public static void main(String[] args)
    {
        int[] arr = { 8, 5, 9, 10, 5, 6, 21, 8 };
        int k = 3;

        // Function call
        int result = maxSum(arr, k);

        // Output result
        System.out.println(result);
    }
}
Python
import sys

def solve(i, prev, k, n, nums, dp):

    # Base Case:
    # If exactly k elements are selected
    if k == 0:
        return 0

    # If array ends before selecting k elements
    if i == n:
        return -sys.maxsize

    # If already computed
    if dp[i][prev + 1][k] != -1:
        return dp[i][prev + 1][k]

    # Option 1: Do not take current element
    not_take = solve(i + 1, prev,
                     k, n, nums, dp)

    # Option 2: Take current element
    take = -sys.maxsize

    # Current element can be selected if:
    # 1. No previous element selected
    # 2. nums[i] >= previous selected value
    if (prev == -1 or
            nums[i] >= nums[prev]):

        next_value = solve(i + 1, i, k - 1, n, nums, dp)

        # Add current value only if next state is valid
        if next_value != -sys.maxsize:
            take = nums[i] + next_value

    # Store and return answer
    dp[i][prev + 1][k] = max(take, not_take)

    return dp[i][prev + 1][k]


def maxSum(a, k):

    n = len(a)

    dp = [[[-1 for _ in range(k + 1)]
           for _ in range(n + 1)]
          for _ in range(n)]

    ans = solve(0, -1, k, n, a, dp)

    # If no valid subsequence exists
    return -1 if ans < 0 else ans


# Driver Code
if __name__ == "__main__":
    arr = [8, 5, 9, 10, 5, 6, 21, 8]

    k = 3

    # Function call
    result = maxSum(arr, k)

    # Output result
    print(result)
C#
using System;

class GFG {

    static long Solve(int i, int prev, int k, int n,
                      int[] nums, long[][][] dp)
    {
        // Base Case:
        // If exactly k elements are selected
        if (k == 0) {
            return 0;
        }

        // If array ends before selecting k elements
        if (i == n) {
            return int.MinValue;
        }

        // If already computed
        if (dp[i][prev + 1][k] != -1) {
            return dp[i][prev + 1][k];
        }

        // Option 1: Do not take current element
        long notTake = Solve(i + 1, prev, k, n, nums, dp);

        // Option 2: Take current element
        long take = int.MinValue;

        // Current element can be selected if :
        // 1. No previous element selected
        // 2. nums[i] >= previous selected value
        if (prev == -1 || nums[i] >= nums[prev]) {

            long next = Solve(i + 1, i, k - 1, n, nums, dp);

            // Add current value only if next state is valid
            if (next != int.MinValue) {
                take = nums[i] + next;
            }
        }

        // Store and return answer
        dp[i][prev + 1][k] = Math.Max(take, notTake);

        return dp[i][prev + 1][k];
    }

    static int maxSum(int[] arr, int k)
    {
        int n = arr.Length;

        // Initialize DP array with -1
        long[][][] dp = new long[n][][];

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

            dp[i] = new long[n + 1][];

            for (int j = 0; j <= n; j++) {

                dp[i][j] = new long[k + 1];

                for (int l = 0; l <= k; l++) {
                    dp[i][j][l] = -1;
                }
            }
        }

        long ans = Solve(0, -1, k, n, arr, dp);

        // If no valid subsequence exists
        return (ans < 0) ? -1 : (int)ans;
    }

    static void Main()
    {
        int[] arr = { 8, 5, 9, 10, 5, 6, 21, 8 };
        int k = 3;

        // Function call
        int result = maxSum(arr, k);

        // Output result
        Console.WriteLine(result);
    }
}
JavaScript
function solve(i, prev, k, n, nums, dp)
{
    // Base Case:
    // If exactly k elements are selected
    if (k === 0) {
        return 0;
    }

    // If array ends before selecting k elements
    if (i === n) {
        return Number.MIN_SAFE_INTEGER;
    }

    // If already computed
    if (dp[i][prev + 1][k] !== -1) {
        return dp[i][prev + 1][k];
    }

    // Option 1: Do not take current element
    let notTake = solve(i + 1, prev, k, n, nums, dp);

    // Option 2: Take current element
    let take = Number.MIN_SAFE_INTEGER;

    // Current element can be selected if:
    // 1. No previous element selected
    // 2. nums[i] >= previous selected value
    if (prev === -1 || nums[i] >= nums[prev]) {

        let next = solve(i + 1, i, k - 1, n, nums, dp);

        // Add current value only if next state is valid
        if (next !== Number.MIN_SAFE_INTEGER) {
            take = nums[i] + next;
        }
    }

    // Store and return answer
    dp[i][prev + 1][k] = Math.max(take, notTake);

    return dp[i][prev + 1][k];
}

function maxSum(a, k)
{
    let n = a.length;

    let dp = Array.from(
        {length : n},
        () => Array.from({length : n + 1},
                         () => Array(k + 1).fill(-1)));

    let ans = solve(0, -1, k, n, a, dp);

    // If no valid subsequence exists
    return (ans < 0) ? -1 : ans;
}

// Driver Code
let arr = [ 8, 5, 9, 10, 5, 6, 21, 8 ];
let k = 3;

// Function call
let result = maxSum(arr, k);

// Output result
console.log(result);

Output
40

[Expected Approach] Using Bottom Up(DP) - O(n ^ 2 * k) Time and O(n * k) Space

In the bottom-up approach, we iteratively build solutions for smaller subsequences first and then use them to construct larger subsequences. The DP table helps us keep track of the maximum sum of non-decreasing subsequences of different lengths ending at every index, which finally allows us to compute the required answer efficiently.

Consider the following example for better understanding: arr = {8, 5, 9}, k = 2

  • Initialize DP table : Base Case --> Sequence of length 1:
    dp[0][1] = 8
    dp[1][1] = 5
    dp[2][1] = 9
  • Subsequence of length 2:
  • For i = 0 ---> No j < i so no update
  • For i = 1, j = 0 ---> check: arr[1] >= arr[0] ---> 5 >= 8 ---> False ---> No update
  • For i = 2, j = 0 ---> check: arr[2] >= arr[0] ---> 9 >= 8 ---> True
    dp[2][2] = max(-INF, dp[0][1] + 9) = max(-INF, 8 + 9) = 17
  • For i = 2, j = 1 ---> check: arr[2] >= arr[1] ---> 9 >= 5 ---> True
    dp[2][2] = max(17, dp[1][1] + 9) = max(17, 5 + 9) = 17
  • Traverse the DP table to find answer --> Maximum value among dp[i][2] = 17
  • Required Non-Decreasing Subsequence: {8, 9}

Final answer : 17

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

int maxSum(vector<int> &a, int k)
{
    int n = a.size();

    // Edge Case:
    // If k is greater than array size
    if (k > n)
    {
        return -1;
    }

    // dp[i][j] represents: Maximum sum of non-decreasing subsequence
    // of size j ending at index i
    vector<vector<long long>> dp(n, vector<long long>(k + 1, INT_MIN));

    // Base Case: Subsequence of length 1 ending at index i
    // will simply contain a[i]
    for (int i = 0; i < n; i++)
    {
        dp[i][1] = a[i];
    }

    for (int len = 2; len <= k; len++)
    {
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < i; j++)
            {
                //   Current element can extend previous subsequence only if:
                //   a[i] >= a[j]
                if (a[i] >= a[j] && dp[j][len - 1] != INT_MIN)
                {
                    dp[i][len] = max(dp[i][len], dp[j][len - 1] + a[i]);
                }
            }
        }
    }

    // Find maximum sum among all subsequences of size k
    long long ans = INT_MIN;

    for (int i = 0; i < n; i++)
    {
        ans = max(ans, dp[i][k]);
    }

    // If no valid subsequence exists
    return (ans == INT_MIN) ? -1 : ans;
}

int main()
{
    vector<int> arr = {8, 5, 9, 10, 5, 6, 21, 8};
    int k = 3;

    // Function call
    int result = maxSum(arr, k);

    // Output result
    cout << result << endl;

    return 0;
}
Java
import java.util.*;

public class GFG {

    static int maxSum(int[] a, int k)
    {
        int n = a.length;

        // Edge Case:
        // If k is greater than array size
        if (k > n) {
            return -1;
        }

        /*
            dp[i][j] represents:
            Maximum sum of non-decreasing subsequence
            of size j ending at index i
        */
        long[][] dp = new long[n][k + 1];

        // Initialize DP table with minimum value
        for (int i = 0; i < n; i++) {
            Arrays.fill(dp[i], Integer.MIN_VALUE);
        }

        /*
            Base Case:
            Subsequence of length 1 ending at index i
            will simply contain a[i]
        */
        for (int i = 0; i < n; i++) {
            dp[i][1] = a[i];
        }

        for (int len = 2; len <= k; len++) {

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

                for (int j = 0; j < i; j++) {

                    /*
                        Current element can extend
                        previous subsequence only if:
                        a[i] >= a[j]
                    */
                    if (a[i] >= a[j]
                        && dp[j][len - 1]
                               != Integer.MIN_VALUE) {

                        dp[i][len] = Math.max(dp[i][len],
                                              dp[j][len - 1]
                                                  + a[i]);
                    }
                }
            }
        }

        // Find maximum sum among all subsequences of size k
        long ans = Integer.MIN_VALUE;

        for (int i = 0; i < n; i++) {
            ans = Math.max(ans, dp[i][k]);
        }

        // If no valid subsequence exists
        return (ans == Integer.MIN_VALUE) ? -1 : (int)ans;
    }

    public static void main(String[] args)
    {
        int[] arr = { 8, 5, 9, 10, 5, 6, 21, 8 };
        int k = 3;

        // Function call
        int result = maxSum(arr, k);

        // Output result
        System.out.println(result);
    }
}
Python
import sys

def maxSum(a, k):

    n = len(a)

    # Edge Case:
    # If k is greater than array size
    if k > n:
        return -1

    """
        dp[i][j] represents:
        Maximum sum of non-decreasing subsequence
        of size j ending at index i
    """
    dp = [[-sys.maxsize for _ in range(k + 1)] for _ in range(n)]

    """
        Base Case:
        Subsequence of length 1 ending at index i
        will simply contain a[i]
    """
    for i in range(n):
        dp[i][1] = a[i]

    for length in range(2, k + 1):

        for i in range(n):

            for j in range(i):

                """
                    Current element can extend
                    previous subsequence only if:
                    a[i] >= a[j]
                """
                if a[i] >= a[j] and dp[j][length - 1] != -sys.maxsize:

                    dp[i][length] = max(dp[i][length],
                                        dp[j][length - 1] + a[i])

    # Find maximum sum among all subsequences of size k
    ans = -sys.maxsize

    for i in range(n):
        ans = max(ans, dp[i][k])

    # If no valid subsequence exists
    return -1 if ans == -sys.maxsize else ans


# Driver Code
if __name__ == "__main__":
 arr = [8, 5, 9, 10, 5, 6, 21, 8]

 k = 3

 # Function call
 result = maxSum(arr, k)

 # Output result
 print(result)
C#
using System;

class GFG {

    static int maxSum(int[] arr, int k)
    {
        int n = arr.Length;

        // Edge Case:
        // If k is greater than array size
        if (k > n) {
            return -1;
        }

        /*
            dp[i][j] represents:
            Maximum sum of non-decreasing subsequence
            of size j ending at index i
        */
        long[, ] dp = new long[n, k + 1];

        // Initialize DP table with minimum value
        for (int i = 0; i < n; i++) {
            for (int j = 0; j <= k; j++) {
                dp[i, j] = int.MinValue;
            }
        }

        /*
            Base Case:
            Subsequence of length 1 ending at index i
            will simply contain arr[i]
        */
        for (int i = 0; i < n; i++) {
            dp[i, 1] = arr[i];
        }

        for (int len = 2; len <= k; len++) {

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

                for (int j = 0; j < i; j++) {

                    /*
                        Current element can extend
                        previous subsequence only if:
                        arr[i] >= arr[j]
                    */
                    if (arr[i] >= arr[j]
                        && dp[j, len - 1] != int.MinValue) {

                        dp[i, len] = Math.Max(dp[i, len],
                                              dp[j, len - 1]
                                                  + arr[i]);
                    }
                }
            }
        }

        // Find maximum sum among all subsequences of size k
        long ans = int.MinValue;

        for (int i = 0; i < n; i++) {
            ans = Math.Max(ans, dp[i, k]);
        }

        // If no valid subsequence exists
        return (ans == int.MinValue) ? -1 : (int)ans;
    }

    static void Main()
    {
        int[] arr = { 8, 5, 9, 10, 5, 6, 21, 8 };
        int k = 3;

        // Function call
        int result = maxSum(arr, k);

        // Output result
        Console.WriteLine(result);
    }
}
JavaScript
function maxSum(a, k)
{
    let n = a.length;

    // Edge Case:
    // If k is greater than array size
    if (k > n) {
        return -1;
    }

    /*
        dp[i][j] represents:
        Maximum sum of non-decreasing subsequence
        of size j ending at index i
    */
    let dp = Array.from(
        {length : n},
        () => Array(k + 1).fill(Number.MIN_SAFE_INTEGER));

    /*
        Base Case:
        Subsequence of length 1 ending at index i
        will simply contain a[i]
    */
    for (let i = 0; i < n; i++) {
        dp[i][1] = a[i];
    }

    for (let len = 2; len <= k; len++) {

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

            for (let j = 0; j < i; j++) {

                /*
                    Current element can extend
                    previous subsequence only if:
                    a[i] >= a[j]
                */
                if (a[i] >= a[j]
                    && dp[j][len - 1]
                           !== Number.MIN_SAFE_INTEGER) {

                    dp[i][len] = Math.max(
                        dp[i][len], dp[j][len - 1] + a[i]);
                }
            }
        }
    }

    // Find maximum sum among all subsequences of size k
    let ans = Number.MIN_SAFE_INTEGER;

    for (let i = 0; i < n; i++) {
        ans = Math.max(ans, dp[i][k]);
    }

    // If no valid subsequence exists
    return (ans === Number.MIN_SAFE_INTEGER) ? -1 : ans;
}

// Driver Code
let arr = [ 8, 5, 9, 10, 5, 6, 21, 8 ];
let k = 3;

// Function call
let result = maxSum(arr, k);

// Output result
console.log(result);

Output
40
Comment