给定一个由N 个整数组成的数组arr[] ,任务是找到最长的子序列,使得子序列每个位置的前缀和都是非负的。
例子:
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
朴素方法:解决此问题的最简单方法是生成给定数组的所有可能子序列,并打印每个位置具有非负前缀和且长度最大的子序列的长度。
时间复杂度: O(2 N )
辅助空间: O(2 N )
高效方法:上述方法也可以使用动态规划进行优化,因为它具有重叠子问题属性和最优子结构属性。与其他动态规划 (DP) 问题一样,可以通过构造一个存储子问题结果的临时数组来避免对相同子问题的重新计算。请按照以下步骤解决问题:
- 初始化一个矩阵,比如dp[][]其中dp[i][j]存储可能的最大和,如果有j 个有效元素直到位置i和 用-1初始化dp[][]数组。
- 使用变量i迭代范围[0, N – 1]并将dp[i][0]更新为0 。
- 如果arr[0]的值至少为0 ,则将dp[0][1]更新为arr[0] 。否则,将其更新为-1 。
- 使用变量i在范围[1, N – 1] 上迭代:
- 使用变量j迭代范围[1, i + 1] :
- 如果当前元素被排除,即,如果dp[i – 1][j]不等于-1 ,则将dp[i][j]更新为dp[i][j]和dp[i – 1] 的最大值[j] .
- 如果包含当前元素,即,如果dp[i – 1][j – 1]和dp[i – 1][j – 1] + arr[i]大于等于0 ,则更新dp[的值i][j]作为dp[i][j]和dp[i – 1][j – 1] + arr[i]的最大值。
- 使用变量j迭代范围[1, i + 1] :
- 初始化一个变量,例如ans为0以存储每个位置具有非负前缀和的最长子序列。
- 使用变量j在范围[0, N] 中迭代,如果dp[N – 1][j]大于等于0 ,则将ans的值更新为j 。
- 完成以上步骤后,打印ans的值作为结果。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
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
5
时间复杂度: O(N 2 )
辅助空间: O(N 2 )
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。