给定由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的2d 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
输出:
5
时间复杂度: O(N)
辅助空间: O(N)