Longest subsequence with non negative prefix sum at each position
Last Updated :
29 Aug, 2023
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:
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++
#include <bits/stdc++.h>
using namespace std;
void longestSubsequence( int * arr, int N)
{
int dp[N][N + 1];
memset (dp, -1, sizeof dp);
for ( int i = 0; i < N; ++i) {
dp[i][0] = 0;
}
dp[0][1] = (arr[0] >= 0 ? arr[0] : -1);
for ( int i = 1; i < N; ++i) {
for ( int j = 1;
j <= (i + 1); ++j) {
if (dp[i - 1][j] != -1) {
dp[i][j] = max(
dp[i][j], dp[i - 1][j]);
}
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;
for ( int j = 0; j <= N; ++j) {
if (dp[N - 1][j] >= 0) {
ans = j;
}
}
cout << ans << endl;
}
int main()
{
int arr[] = { 4, -4, 1, -3, 1, -3 };
int N = sizeof arr / sizeof arr[0];
longestSubsequence(arr, N);
return 0;
}
|
Java
import java.lang.*;
import java.util.*;
class GFG{
static void longestSubsequence( int [] arr, int N)
{
int dp[][] = new int [N][N + 1 ];
for ( int i = 0 ; i < N; ++i)
{
for ( int j = 0 ; j < N + 1 ; ++j)
{
dp[i][j] = - 1 ;
}
}
for ( int i = 0 ; i < N; ++i)
{
dp[i][ 0 ] = 0 ;
}
dp[ 0 ][ 1 ] = (arr[ 0 ] >= 0 ? arr[ 0 ] : - 1 );
for ( int i = 1 ; i < N; ++i)
{
for ( int j = 1 ; j <= (i + 1 ); ++j)
{
if (dp[i - 1 ][j] != - 1 )
{
dp[i][j] = Math.max(
dp[i][j], dp[i - 1 ][j]);
}
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 ;
for ( int j = 0 ; j <= N; ++j)
{
if (dp[N - 1 ][j] >= 0 )
{
ans = j;
}
}
System.out.println(ans);
}
public static void main(String[] args)
{
int arr[] = { 4 , - 4 , 1 , - 3 , 1 , - 3 };
int N = arr.length;
longestSubsequence(arr, N);
}
}
|
Python3
def longestSubsequence(arr, N):
dp = [[ - 1 for i in range (N + 1 )] for i in range (N)]
for i in range (N):
dp[i][ 0 ] = 0
dp[ 0 ][ 1 ] = arr[ 0 ] if arr[ 0 ] > = 0 else - 1
for i in range ( 1 , N):
for j in range ( 1 , i + 2 ):
if (dp[i - 1 ][j] ! = - 1 ):
dp[i][j] = max (dp[i][j], dp[i - 1 ][j])
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
for j in range (N + 1 ):
if (dp[N - 1 ][j] > = 0 ):
ans = j
print (ans)
arr = [ 4 , - 4 , 1 , - 3 , 1 , - 3 ]
N = len (arr)
longestSubsequence(arr, N)
|
C#
using System;
class GFG{
static void longestSubsequence( int [] arr, int N)
{
int [,] dp = new int [N, N + 1];
for ( int i = 0; i < N; ++i)
{
for ( int j = 0; j < N + 1; ++j)
{
dp[i, j] = -1;
}
}
for ( int i = 0; i < N; ++i)
{
dp[i, 0] = 0;
}
dp[0, 1] = (arr[0] >= 0 ? arr[0] : -1);
for ( int i = 1; i < N; ++i)
{
for ( int j = 1; j <= (i + 1); ++j)
{
if (dp[i - 1, j] != -1)
{
dp[i, j] = Math.Max(dp[i, j],
dp[i - 1, j]);
}
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;
for ( int j = 0; j <= N; ++j)
{
if (dp[N - 1, j] >= 0)
{
ans = j;
}
}
Console.Write(ans);
}
public static void Main()
{
int [] arr = { 4, -4, 1, -3, 1, -3 };
int N = arr.Length;
longestSubsequence(arr, N);
}
}
|
Javascript
<script>
function longestSubsequence(arr, N)
{
let dp = Array(N).fill().map(() => Array(N + 1).fill(-1));
for (let i = 0; i < N; ++i) {
dp[i][0] = 0;
}
dp[0][1] = (arr[0] >= 0 ? arr[0] : -1);
for (let i = 1; i < N; ++i) {
for (let j = 1;
j <= (i + 1); ++j) {
if (dp[i - 1][j] != -1) {
dp[i][j] = Math.max(
dp[i][j], dp[i - 1][j]);
}
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;
for (let j = 0; j <= N; ++j) {
if (dp[N - 1][j] >= 0) {
ans = j;
}
}
document.write(ans);
}
let arr = [4, -4, 1, -3, 1, -3];
let N = arr.length;
longestSubsequence(arr, N);
</script>
|
Time Complexity: O(N2)
Auxiliary Space: O(N2)
Efficient approach : Space optimization
In previous approach the current value dp[i][j] is only depend upon the current and previous row values of DP. So to optimize the space complexity we use a single 1D array to store the computations.
Implementation steps:
- Create a 1D vector dp of size N+1.
- Set a base case by initializing the values of DP .
- Now iterate over subproblems by the help of nested loop and get the current value from previous computations.
- Initialize a variable ans to store the final answer and update it by iterating through the Dp.
- At last return and print the final answer stored in ans .
Implementation:
C++
#include <bits/stdc++.h>
using namespace std;
void longestSubsequence( int * arr, int N)
{
int dp[N + 1];
memset (dp, -1, sizeof dp);
dp[0] = 0;
dp[1] = (arr[0] >= 0 ? arr[0] : -1);
for ( int i = 1; i < N; ++i) {
for ( int j = min(i + 1, N); j >= 1; --j) {
if (dp[j] != -1) {
dp[j] = max(dp[j], dp[j - 1] + arr[i]);
}
if (dp[j - 1] >= 0 && dp[j - 1] + arr[i] >= 0) {
dp[j] = max(dp[j], dp[j - 1] + arr[i]);
}
}
}
int ans = 0;
for ( int j = 0; j <= N; ++j) {
if (dp[j] >= 0) {
ans = j;
}
}
cout << ans << endl;
}
int main()
{
int arr[] = { 4, -4, 1, -3, 1, -3 };
int N = sizeof arr / sizeof arr[0];
longestSubsequence(arr, N);
return 0;
}
|
Java
import java.util.Arrays;
public class Main
{
public static void longestSubsequence( int [] arr, int N)
{
int [] dp = new int [N + 1 ];
Arrays.fill(dp, - 1 );
dp[ 0 ] = 0 ;
dp[ 1 ] = (arr[ 0 ] >= 0 ? arr[ 0 ] : - 1 );
for ( int i = 1 ; i < N; ++i) {
for ( int j = Math.min(i + 1 , N); j >= 1 ; --j) {
if (dp[j] != - 1 ) {
dp[j] = Math.max(dp[j], dp[j - 1 ] + arr[i]);
}
if (dp[j - 1 ] >= 0 && dp[j - 1 ] + arr[i] >= 0 ) {
dp[j] = Math.max(dp[j], dp[j - 1 ] + arr[i]);
}
}
}
int ans = 0 ;
for ( int j = 0 ; j <= N; ++j) {
if (dp[j] >= 0 ) {
ans = j;
}
}
System.out.println(ans);
}
public static void main(String[] args) {
int [] arr = { 4 , - 4 , 1 , - 3 , 1 , - 3 };
int N = arr.length;
longestSubsequence(arr, N);
}
}
|
Python
def longestSubsequence(arr, N):
dp = [ - 1 ] * (N + 1 )
dp[ 0 ] = 0
dp[ 1 ] = arr[ 0 ] if arr[ 0 ] > = 0 else - 1
for i in range ( 1 , N):
for j in range ( min (i + 1 , N), 0 , - 1 ):
if dp[j] ! = - 1 :
dp[j] = max (dp[j], dp[j - 1 ] + arr[i])
if dp[j - 1 ] > = 0 and dp[j - 1 ] + arr[i] > = 0 :
dp[j] = max (dp[j], dp[j - 1 ] + arr[i])
ans = 0
for j in range (N + 1 ):
if dp[j] > = 0 :
ans = j
print (ans)
if __name__ = = '__main__' :
arr = [ 4 , - 4 , 1 , - 3 , 1 , - 3 ]
N = len (arr)
longestSubsequence(arr, N)
|
C#
using System;
class GFG
{
static void longestSubsequence( int [] arr, int N)
{
int [] dp = new int [N + 1];
Array.Fill(dp, -1);
dp[0] = 0;
dp[1] = (arr[0] >= 0 ? arr[0] : -1);
for ( int i = 1; i < N; ++i)
{
for ( int j = Math.Min(i + 1, N); j >= 1; --j)
{
if (dp[j] != -1)
{
dp[j] = Math.Max(dp[j], dp[j - 1] + arr[i]);
}
if (dp[j - 1] >= 0 && dp[j - 1] + arr[i] >= 0)
{
dp[j] = Math.Max(dp[j], dp[j - 1] + arr[i]);
}
}
}
int ans = 0;
for ( int j = 0; j <= N; ++j)
{
if (dp[j] >= 0)
{
ans = j;
}
}
Console.WriteLine(ans);
}
static void Main( string [] args)
{
int [] arr = { 4, -4, 1, -3, 1, -3 };
int N = arr.Length;
longestSubsequence(arr, N);
}
}
|
Javascript
function longestSubsequence(arr, N) {
let dp = new Array(N + 1).fill(-1);
dp[0] = 0;
dp[1] = arr[0] >= 0 ? arr[0] : -1;
for (let i = 1; i < N; ++i) {
for (let j = Math.min(i + 1, N); j >= 1; --j) {
if (dp[j] !== -1) {
dp[j] = Math.max(dp[j], dp[j - 1] + arr[i]);
}
if (dp[j - 1] >= 0 && dp[j - 1] + arr[i] >= 0) {
dp[j] = Math.max(dp[j], dp[j - 1] + arr[i]);
}
}
}
let ans = 0;
for (let j = 0; j <= N; ++j) {
if (dp[j] >= 0) {
ans = j;
}
}
console.log(ans);
}
let arr = [4, -4, 1, -3, 1, -3];
let N = arr.length;
longestSubsequence(arr, N);
|
Output:
5
Time Complexity: O(N^2)
Auxiliary Space: O(N)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...