Skip to content
Related Articles

Related Articles

Save Article
Improve Article
Save Article
Like Article

Longest subsequence with non negative prefix sum at each position

  • Difficulty Level : Hard
  • Last Updated : 28 Jul, 2021

Given an array arr[] consisting of N integers, the task is to find the longest subsequence such that the prefix sum at each position of the subsequence is non-negative.

Examples:

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.

Input: arr[] = {4, -4, 1, -3, 1, -3}
Output: 5
Explanation:
Consider the subsequence as {4, 1, -3, 1, -3}. Now, the prefix sum of the chosen subsequence is {4, 5, 2, 3, 0}. Since, the prefix sum is non-negative at every possible index. Therefore, this subsequence is of maximum length having length 5.



Input: arr[] = {1, 3, 5, 7}
Output: 4

Naive Approach: The simplest approach to solve this problem is to generate all possible subsequences of the given array and print the length of that subsequence that has a non-negative prefix sum at each position and is of maximum length.

Time Complexity: O(2N)
Auxiliary Space: O(2N)

Efficient Approach: The above approach can also be optimized by using Dynamic Programming because it has Overlapping Subproblems property and Optimal Substructure property. Like other Dynamic Programming(DP) problems, recomputation of the same subproblems can be avoided by constructing a temporary array that stores the results of subproblems. Follow the steps below to solve the problem:

  • Initialize a matrix, say dp[][] where dp[i][j] stores the maximum sum possible if there are j valid elements till position i and initializing dp[][] array with -1.
  • Iterate over the range [0, N – 1] using the variable i and update dp[i][0] as 0.
  • If the value of arr[0] is at least 0, then update dp[0][1] as arr[0]. Otherwise, update it as -1.
  • Iterate over the range [1, N – 1] using the variable i:
    • Iterate over the range [1, i + 1] using the variable j:
      • If current element is excluded i.e., if dp[i – 1][j] is not equal to -1, then update dp[i][j] as max of dp[i][j] and dp[i – 1][j].
      • If current element is included i.e., if dp[i – 1][j – 1] and dp[i – 1][j – 1] + arr[i] are greater than equal to 0, then update the value of dp[i][j] as the maximum of dp[i][j] and dp[i – 1][j – 1] + arr[i].
  • Initialize a variable say, ans as 0 to store the longest subsequence with non-negative prefix sum at each position.
  • Iterate in the range [0, N] using the variable j and if dp[N – 1][j] is greater than equal to 0, then update the value of ans as j.
  • After completing the above steps, print the value of ans as the result.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to find the length of the
// longest subsequence with non negative
// prefix sum at each position
void longestSubsequence(int* arr, int N)
{
    // Stores the maximum sum possible
    // if we include j elements till
    // the position i
    int dp[N][N + 1];
 
    // Initialize dp array with -1
    memset(dp, -1, sizeof dp);
 
    // Maximum subsequence sum by
    // including no elements till
    // position 'i'
    for (int i = 0; i < N; ++i) {
        dp[i][0] = 0;
    }
 
    // Maximum subsequence sum by
    // including first element at
    // first position
    dp[0][1] = (arr[0] >= 0 ? arr[0] : -1);
 
    // Iterate over all the remaining
    // positions
    for (int i = 1; i < N; ++i) {
 
        for (int j = 1;
             j <= (i + 1); ++j) {
 
            // If the current element
            // is excluded
            if (dp[i - 1][j] != -1) {
                dp[i][j] = max(
                    dp[i][j], dp[i - 1][j]);
            }
 
            // If current element is
            // included and if total
            // sum is positive or not
            if (dp[i - 1][j - 1] >= 0
                && dp[i - 1][j - 1]
                           + arr[i]
                       >= 0) {
 
                dp[i][j] = max(
                    dp[i][j],
                    dp[i - 1][j - 1]
                        + arr[i]);
            }
        }
    }
 
    int ans = 0;
 
    // Select the maximum j by which
    // a non negative prefix sum
    // subsequence can be obtained
    for (int j = 0; j <= N; ++j) {
        if (dp[N - 1][j] >= 0) {
            ans = j;
        }
    }
 
    // Print the answer
    cout << ans << endl;
}
 
// Driver Code
int main()
{
    int arr[] = { 4, -4, 1, -3, 1, -3 };
    int N = sizeof arr / sizeof arr[0];
    longestSubsequence(arr, N);
 
    return 0;
}

Java




// Java program for the above approach
import java.lang.*;
import java.util.*;
 
class GFG{
 
// Function to find the length of the
// longest subsequence with non negative
// prefix sum at each position
static void longestSubsequence(int[] arr, int N)
{
     
    // Stores the maximum sum possible
    // if we include j elements till
    // the position i
    int dp[][] = new int[N][N + 1];
 
    // Initialize dp array with -1
    for(int i = 0; i < N; ++i)
    {
        for(int j = 0; j < N + 1; ++j)
        {
            dp[i][j] = -1;
        }
    }
     
    // Maximum subsequence sum by
    // including no elements till
    // position 'i'
    for(int i = 0; i < N; ++i)
    {
        dp[i][0] = 0;
    }
 
    // Maximum subsequence sum by
    // including first element at
    // first position
    dp[0][1] = (arr[0] >= 0 ? arr[0] : -1);
 
    // Iterate over all the remaining
    // positions
    for(int i = 1; i < N; ++i)
    {
        for(int j = 1; j <= (i + 1); ++j)
        {
             
            // If the current element
            // is excluded
            if (dp[i - 1][j] != -1)
            {
                dp[i][j] = Math.max(
                    dp[i][j], dp[i - 1][j]);
            }
 
            // If current element is
            // included and if total
            // sum is positive or not
            if (dp[i - 1][j - 1] >= 0 &&
                dp[i - 1][j - 1] + arr[i] >= 0)
            {
                dp[i][j] = Math.max(dp[i][j],
                                    dp[i - 1][j - 1] +
                                   arr[i]);
            }
        }
    }
 
    int ans = 0;
 
    // Select the maximum j by which
    // a non negative prefix sum
    // subsequence can be obtained
    for(int j = 0; j <= N; ++j)
    {
        if (dp[N - 1][j] >= 0)
        {
            ans = j;
        }
    }
 
    // Print the answer
    System.out.println(ans);
}
 
// Driver code
public static void main(String[] args)
{
    int arr[] = { 4, -4, 1, -3, 1, -3 };
    int N = arr.length;
     
    longestSubsequence(arr, N);
}
}
 
// This code is contributed by avijitmondal1998

Python3




# Python3 Program for the above approach
 
# Function to find the length of the
# longest subsequence with non negative
# prefix sum at each position
def longestSubsequence(arr, N):
 
    # Stores the maximum sum possible
    # if we include j elements till
    # the position i
 
    # Initialize dp array with -1
    dp = [[-1 for i in range(N + 1)] for i in range(N)]
 
    # Maximum subsequence sum by
    # including no elements till
    # position 'i'
    for i in range(N):
        dp[i][0] = 0
 
    # Maximum subsequence sum by
    # including first element at
    # first position
    dp[0][1] = arr[0] if arr[0] >= 0 else -1
 
    # Iterate over all the remaining
    # positions
    for i in range(1, N):
 
        for j in range(1, i + 2):
 
            # If the current element
            # is excluded
            if (dp[i - 1][j] != -1):
                dp[i][j] = max(dp[i][j], dp[i - 1][j])
 
            # If current element is
            # included and if total
            # sum is positive or not
            if (dp[i - 1][j - 1] >= 0 and dp[i - 1][j - 1] + arr[i] >= 0):
 
                dp[i][j] = max(dp[i][j], dp[i - 1][j - 1] + arr[i])
 
    ans = 0
 
    # Select the maximum j by which
    # a non negative prefix sum
    # subsequence can be obtained
    for j in range(N + 1):
        if (dp[N - 1][j] >= 0):
            ans = j
 
    # Print the answer
    print(ans)
 
# Driver Code
 
 
arr = [4, -4, 1, -3, 1, -3]
N = len(arr)
longestSubsequence(arr, N)
 
# This code is contributed by _saurabhy_jaiswal

C#




// C# program for the above approach
using System;
 
class GFG{
 
// Function to find the length of the
// longest subsequence with non negative
// prefix sum at each position
static void longestSubsequence(int[] arr, int N)
{
     
    // Stores the maximum sum possible
    // if we include j elements till
    // the position i
    int[,] dp = new int[N, N + 1];
 
    // Initialize dp array with -1
    for(int i = 0; i < N; ++i)
    {
        for(int j = 0; j < N + 1; ++j)
        {
            dp[i, j] = -1;
        }
    }
 
    // Maximum subsequence sum by
    // including no elements till
    // position 'i'
    for(int i = 0; i < N; ++i)
    {
        dp[i, 0] = 0;
    }
 
    // Maximum subsequence sum by
    // including first element at
    // first position
    dp[0, 1] = (arr[0] >= 0 ? arr[0] : -1);
 
    // Iterate over all the remaining
    // positions
    for(int i = 1; i < N; ++i)
    {
        for(int j = 1; j <= (i + 1); ++j)
        {
             
            // If the current element
            // is excluded
            if (dp[i - 1, j] != -1)
            {
                dp[i, j] = Math.Max(dp[i, j],
                                    dp[i - 1, j]);
            }
 
            // If current element is
            // included and if total
            // sum is positive or not
            if (dp[i - 1, j - 1] >= 0 &&
                dp[i - 1, j - 1] + arr[i] >= 0)
            {
                dp[i, j] = Math.Max(dp[i, j],
                                    dp[i - 1, j - 1] +
                                    arr[i]);
            }
        }
    }
 
    int ans = 0;
 
    // Select the maximum j by which
    // a non negative prefix sum
    // subsequence can be obtained
    for(int j = 0; j <= N; ++j)
    {
        if (dp[N - 1, j] >= 0)
        {
            ans = j;
        }
    }
 
    // Print the answer
    Console.Write(ans);
}
 
// Driver code
public static void Main()
{
    int[] arr = { 4, -4, 1, -3, 1, -3 };
    int N = arr.Length;
 
    longestSubsequence(arr, N);
}
}
 
// This code is contributed by ukasp

Javascript




<script>
       // JavaScript Program for the above approach
 
       // Function to find the length of the
       // longest subsequence with non negative
       // prefix sum at each position
       function longestSubsequence(arr, N)
       {
        
           // Stores the maximum sum possible
           // if we include j elements till
           // the position i
 
           // Initialize dp array with -1
           let dp = Array(N).fill().map(() => Array(N + 1).fill(-1));
 
 
           // Maximum subsequence sum by
           // including no elements till
           // position 'i'
           for (let i = 0; i < N; ++i) {
               dp[i][0] = 0;
           }
 
           // Maximum subsequence sum by
           // including first element at
           // first position
           dp[0][1] = (arr[0] >= 0 ? arr[0] : -1);
 
           // Iterate over all the remaining
           // positions
           for (let i = 1; i < N; ++i) {
 
               for (let j = 1;
                   j <= (i + 1); ++j) {
 
                   // If the current element
                   // is excluded
                   if (dp[i - 1][j] != -1) {
                       dp[i][j] = Math.max(
                           dp[i][j], dp[i - 1][j]);
                   }
 
                   // If current element is
                   // included and if total
                   // sum is positive or not
                   if (dp[i - 1][j - 1] >= 0
                       && dp[i - 1][j - 1]
                       + arr[i]
                       >= 0) {
 
                       dp[i][j] = Math.max(
                           dp[i][j],
                           dp[i - 1][j - 1]
                           + arr[i]);
                   }
               }
           }
 
           let ans = 0;
 
           // Select the maximum j by which
           // a non negative prefix sum
           // subsequence can be obtained
           for (let j = 0; j <= N; ++j) {
               if (dp[N - 1][j] >= 0) {
                   ans = j;
               }
           }
 
           // Print the answer
           document.write(ans);
       }
 
       // Driver Code
 
       let arr = [4, -4, 1, -3, 1, -3];
       let N = arr.length;
       longestSubsequence(arr, N);
 
   // This code is contributed by Potta Lokesh
 
   </script>
Output: 
5

 

Time Complexity: O(N2)
Auxiliary Space: O(N2)




My Personal Notes arrow_drop_up
Recommended Articles
Page :