给定一个由N 个正整数组成的数组arr[] ,任务是从给定数组中找到子序列的最大和,使得子序列中的元素交替分配正负号。
Subsequence = {a, b, c, d, e, … },
Sum of the above subsequence = (a – b + c – d + e – …)
例子:
Input: arr[] = {1, 2, 3, 4}
Output: 4
Explanation:
The subsequence having maximum sum is {4}.
The sum is 4.
Input: arr[]= {1, 2, 3, 4, 1, 2 }
Output: 5
Explanation:
The subsequence having maximum sum is {4, 1, 2}.
The sum = 4 -1 + 2 = 5.
朴素的方法:最简单的方法是生成给定数组的所有子序列,然后找到每个子序列的总和,并打印所有子序列总和中的最大值。
时间复杂度: O(N*2 N )
辅助空间: O(1)
高效的方法:为了优化上述方法,思想是使用动态规划。初始化一个大小为N*2的辅助空间dp[][]来存储重叠子问题。在每个递归调用中,将arr[i]或(-1)*arr[i] 添加到带有表示当前元素是正还是负的相应标志变量的总和中。以下是步骤:
- 创建一个大小为N*2的二维dp[][]数组并使用-1初始化该数组。
- 传递表示元素符号的变量标志必须在下一项中选择。例如,在子序列{a, b, c} 中,最大子序列可以是(a – b + c)或(b – c)或c。不是对所有重叠子问题重复出现,而是一次又一次地在dp[][]数组中存储一次并使用重复状态。
- 如果标志为 0,则当前元素将被视为正元素,如果标志为 1,则当前元素将被视为负元素。
- 将每个结果存储到dp[][]数组中。
- 打印dp[N][flag] 的值作为上述步骤后的最大和。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to find the
// maximum sum subsequence
int findMax(vector& a, int dp[][2],
int i, int flag)
{
// Base Case
if (i == (int)a.size()) {
return 0;
}
// If current state is already
// calculated then use it
if (dp[i][flag] != -1) {
return dp[i][flag];
}
int ans;
// If current element is positive
if (flag == 0) {
// Update ans and recursively
// call with update value of flag
ans = max(findMax(a, dp, i + 1, 0),
a[i]
+ findMax(a, dp,
i + 1, 1));
}
// Else current element is negative
else {
// Update ans and recursively
// call with update value of flag
ans = max(findMax(a, dp, i + 1, 1),
-1 * a[i]
+ findMax(a, dp,
i + 1, 0));
}
// Return maximum sum subsequence
return dp[i][flag] = ans;
}
// Function that finds the maximum
// sum of element of the subsequence
// with alternate +ve and -ve signs
void findMaxSumUtil(vector& arr,
int N)
{
// Create auxiliary array dp[][]
int dp[N][2];
// Initialize dp[][]
memset(dp, -1, sizeof dp);
// Function Call
cout << findMax(arr, dp, 0, 0);
}
// Driver Code
int main()
{
// Given array arr[]
vector arr = { 1, 2, 3, 4, 1, 2 };
int N = arr.size();
// Function Call
findMaxSumUtil(arr, N);
return 0;
}
Java
// Java program for the above approach
import java.io.*;
import java.util.Arrays;
class GFG{
// Function to find the
// maximum sum subsequence
static int findMax(int[] a, int dp[][],
int i, int flag)
{
// Base Case
if (i == (int)a.length)
{
return 0;
}
// If current state is already
// calculated then use it
if (dp[i][flag] != -1)
{
return dp[i][flag];
}
int ans;
// If current element is positive
if (flag == 0)
{
// Update ans and recursively
// call with update value of flag
ans = Math.max(findMax(a, dp, i + 1, 0),
a[i] + findMax(a, dp, i + 1, 1));
}
// Else current element is negative
else
{
// Update ans and recursively
// call with update value of flag
ans = Math.max(findMax(a, dp, i + 1, 1),
-1 * a[i] + findMax(a, dp, i + 1, 0));
}
// Return maximum sum subsequence
return dp[i][flag] = ans;
}
// Function that finds the maximum
// sum of element of the subsequence
// with alternate +ve and -ve signs
static void findMaxSumUtil(int[] arr,
int N)
{
// Create auxiliary array dp[][]
int dp[][] = new int[N][2];
// Initialize dp[][]
for(int i = 0; i < N; i++)
{
for(int j = 0; j < 2; j++)
{
dp[i][j] = -1;
}
}
// Function Call
System.out.println(findMax(arr, dp, 0, 0));
}
// Driver Code
public static void main (String[] args)
{
// Given array arr[]
int[] arr = { 1, 2, 3, 4, 1, 2 };
int N = arr.length;
// Function call
findMaxSumUtil(arr, N);
}
}
// This code is contributed by sanjoy_62
Python3
# Python3 program for the above approach
# Function to find the
# maximum sum subsequence
def findMax(a, dp, i, flag):
# Base Case
if (i == len(a)):
return 0
# If current state is already
# calculated then use it
if (dp[i][flag] != -1):
return dp[i][flag]
ans = 0
# If current element is positive
if (flag == 0):
# Update ans and recursively
# call with update value of flag
ans = max(findMax(a, dp, i + 1, 0),
a[i] + findMax(a, dp, i + 1, 1))
# Else current element is negative
else:
# Update ans and recursively
# call with update value of flag
ans = max(findMax(a, dp, i + 1, 1),
-1 * a[i] + findMax(a, dp, i + 1, 0))
# Return maximum sum subsequence
dp[i][flag] = ans
return ans
# Function that finds the maximum
# sum of element of the subsequence
# with alternate +ve and -ve signs
def findMaxSumUtil(arr, N):
# Create auxiliary array dp[][]
dp = [[-1 for i in range(2)]
for i in range(N)]
# Function call
print(findMax(arr, dp, 0, 0))
# Driver Code
if __name__ == '__main__':
# Given array arr[]
arr = [ 1, 2, 3, 4, 1, 2 ]
N = len(arr)
# Function call
findMaxSumUtil(arr, N)
# This code is contributed by mohit kumar 29
C#
// C# program for the above approach
using System;
class GFG {
// Function to find the
// maximum sum subsequence
static int findMax(int[] a, int[,] dp,
int i, int flag)
{
// Base Case
if (i == (int)a.Length)
{
return 0;
}
// If current state is already
// calculated then use it
if (dp[i, flag] != -1)
{
return dp[i, flag];
}
int ans;
// If current element is positive
if (flag == 0)
{
// Update ans and recursively
// call with update value of flag
ans = Math.Max(findMax(a, dp, i + 1, 0),
a[i] + findMax(a, dp, i + 1, 1));
}
// Else current element is negative
else
{
// Update ans and recursively
// call with update value of flag
ans = Math.Max(findMax(a, dp, i + 1, 1),
-1 * a[i] + findMax(a, dp, i + 1, 0));
}
// Return maximum sum subsequence
return dp[i, flag] = ans;
}
// Function that finds the maximum
// sum of element of the subsequence
// with alternate +ve and -ve signs
static void findMaxSumUtil(int[] arr,
int N)
{
// Create auxiliary array dp[][]
int[,] dp = new int[N, 2];
// Initialize dp[][]
for(int i = 0; i < N; i++)
{
for(int j = 0; j < 2; j++)
{
dp[i, j] = -1;
}
}
// Function Call
Console.WriteLine(findMax(arr, dp, 0, 0));
}
// Driver Code
public static void Main()
{
// Given array arr[]
int[] arr = { 1, 2, 3, 4, 1, 2 };
int N = arr.Length;
// Function call
findMaxSumUtil(arr, N);
}
}
// This code is contributed by code_hunt
Javascript
5
时间复杂度: O(N)
辅助空间: O(N)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。