# Maximum sum subsequence of any size which is decreasing-increasing alternatively

• Difficulty Level : Hard
• Last Updated : 11 Jan, 2022

Given an array of integers arr[], find the subsequence with maximum sum whose elements are first decreasing, then increasing, or vice versa, The subsequence can start anywhere in the main sequence, not necessarily at the first element of the main sequence.

A sequence {x1, x2, .. xn} is an alternating sequence if its elements satisfy one of the following relations (As described in the article Longest alternating subsequence)

Two adjacent elements that are equal are not counted as alternating.

x1 < x2 > x3 < x4 > x5 < â€¦. xn
or
x1 > x2 < x3 > x4 < x5 > â€¦. xn

Examples :

Input: arr[] = {4, 8, 2, 5, 6, 8}
Output: 26
Explanation: Alternating subsequence with maximum sum is {4, 8, 6, 8}. Sum = 4 + 8 + 6 + 8 = 26

Input: arr[] = {0, 1, 1, 1, 3, 2, 5}
Output: 11
Explanation: Alternating subsequence with maximum sum is {1, 3, 2, 5}. Sum = 1 + 3 + 2 + 5 = 11

Input: arr[] = {1, 4, 5}
Output: 9
Explanation: Alternating subsequence with maximum sum is {4, 5}. Sum = 4 + 5 = 9

Input: arr[] = {1, 0, 1, 0, 0, 3}
Output: 5
Explanation: Alternating subsequence with maximum sum is {1, 0, 1, 0, 3}. Sum = 1 + 0 + 1 + 0 + 3 = 5

Input: arr[] = {5, 5}
Output: 5
Explanation: Alternating subsequence with maximum sum is {5}. Sum = 5

This problem is an extension of the Maximum sum alternating subsequence problem. Unlike the previous problem, now we need to calculate the maximum sum of the alternating subsequence regardless of where it is in the main sequence, and regardless of whether it starts with two elements ascending or two descending elements.

Approach: This problem can be solved by Dynamic Programming combined with Backtracking. Suppose, we have an array arr[] with any N elements.

• We can consider each arr[i] element as a terminating element of an alternating sequence.
• There can be many alternating subsequences whose last element is arr[i], but surely one of them is the sequence with the greatest sum.
• Furthermore, the maximum sum of the alternating subsequences ending with arr[i] is not necessarily greater than the maximum sum of the alternating subsequences ending with arr[i-1]. And this is the basis for implementing the algorithm according to the Backtracking technique.
• Have an array say maxSum[] of length N which will store all the maximum sums ending at each element in the array arr[]. Specifically, maxSum[i] will store the maximum sum of the alternating subsequence ending at the value arr[i].
• We will use another array before[] to store the value preceding the last element of each alternating subsequence with maximum sum.

For example, an array arr[] = {1, 5, 7, 3, 4, 5} will have an alternating subsequence {5, 7, 3, 4} whose maximum sum is 5 + 7 + 3 + 4 = 19.
The subsequence {5, 7, 3, 4} ends at the value 4, which has index 4 in the array arr[].
So we have arr[4] = 4, maxSum[4] = 19,  before[4] = 3 (because arr[3] = 3).
Those values â€‹â€‹will be calculated and saved into two arrays maxSum[] and before[] during the calculation and can be reused as needed.

Use the following steps to implement the approach:

• Use a loop to iterate through every element of the array arr[]. Each time we traverse an arr[i] element, we look at the elements that precede it:

i Loop traversal from 1 to N-1 (There’s no need to start at position 0, because that’s the base case):
j Loop traversal from 0 to i-1:

• At each state i and j, we will reuse any maxSum[j] with 0 <= j < i according to the principle of Dynamic Programming:

if:
(arr[i] > arr[j] && arr[before[j]] > arr[j])
or
(arr[i] < arr[j] && arr[before[j]] < arr[j])

then:
sum = arr[i] + maxSum[j]

• If maxSum[j] does not satisfy the above condition, it can be two equal elements. Since two equal elements are not treated as an alternating sequence, we only take one of them.

if:
arr[i] == arr[j]

then:
sum = maxSum[j]

• Or it may not be any of the above, like having more than two elements in increasing or having more than two elements in decreasing order.

Example {1, 5, 7, 3, 4, 5}. Suppose we are at i = 5, j = 4

• Then before[4] is the 3-rd element, and (arr[before[j]], arr[j], arr[i]) = (arr[before[4]], arr[4], arr[5]) = (arr[3], arr[4], arr[5]) = (3, 4, 5).
• The above one is not a valid alternating subsequence, meaning that before[j] is not the index of a valid value.
• We will look at the preceding element of arr[before[j]] in its alternating sequence: before[before[j]] = before[3] = 2, and arr[2] with arr[4] and arr[5] form a valid subsequence (7, 4, 5).
• So we get a value of arr[5] + arr[4] + maxSum[2], which is the final sum of state {i = 5, j = 4}.
• We need to compare it with other {i and j} states (like {i = 5, j = 3}, {i = 5, j = 2}…) to get the final result for maxSum[5].
• Then save j into the before[5] if it precedes arr[5] and helps arr[5] form a valid subsequence with a maximum sum at state 5.

Take a look at the illustration below to get the idea clear.

index      :   0  1  2  3  4  5  || N = 6
arr[]      :   1, 5, 7, 3, 4, 5

—————————————————————————————————-

maxSum[0]  :    0  0  0  0  0   = 1 base case
before[-1] :  -1  _  _  _  _  _

maxSum[1]  :   1   0  0  0  0   = 6 because 1 + 5
before[1]  :  -1   _  _  _  _

maxSum[2]  :   1  6 12  0  0  0   = 12 because 1, 5, 7 isn’t alternating subsequence, and just 5 & 7
before[2]  :  -1  0  1  _  _  _    is valid, we use backtracking at index 2 so
we will go through the following subsequence: {1, 7}, {5, 7}. We have {5, 7} because before[1] is index 0,
we continue to find value at before[before[1]] = -1, whose value is 0, so 0 + 5 + 7 = 12 > 1 + 7.

maxSum[3]  :   1  6 12 15  0  0   = 15 because 5, 7, 3 is valid alternating subsequence,
before[3]  :  -1  0  1  2  _  _ so 3 + max(maxSum[2], maxSum[1], maxSum[0]) = 3 + 12.

maxSum[4]  :   1  6 12 15 19  0  = 19 because 5, 7, 3, 4 is valid alternating subsequence,
before[4]  :  -1  0  1  2  3  _   so 4 + max(maxSum[3], maxSum[2],… maxSum[0]) = 4 + 15.

maxSum[5]  :   1  6 12 15 19 21   = 21, arr[5] cannot be the next element of maxSum[4] because 3, 4, 5
before[5]  :  -1  0  1  2  3  2 isn’t alternating subsequence. So we need use backtracking here.
We will treat the value 3 as an invalid value for the alternating subsequence ending in arr[5].
We need to find the preceding element of before[arr[4]] in the sum of maxSum[4] recursively,
that is index 2. Now 7, 4, 5 have formed a valid alternating subsequence.
So we have 5 + max(backtracking(index 4), maxSum[3], maxSum[2],…) = 5 + 16 ( because 4 + 7 + 5)
Then, final max sum of alternating subsequence of arr is max element of “maxSum” array.

Output: 21

Below is the implementation of the above approach:

## C++

 `// C++ code to implement the above approach` `#include ``using` `namespace` `std;` `// Function for backtracking``int` `backtracking(``int` `arr[], ``int` `maxSum[], ``int` `before[],``                 ``int` `N, ``int` `root, ``int` `bef_root,``                 ``int` `bbef_root)``{``    ``// {root, bef_root} represents state{i, j}``    ``// bbef_root represent before[before[j]]``    ``// We ignore the invalid before[j] index` `    ``// Base case:``    ``if` `(bbef_root == -1)``        ``return` `arr[bef_root];` `    ``// The case of a subsequence with``    ``// alternating parts:``    ``if` `((arr[root] > arr[bef_root]``         ``&& arr[bbef_root] > arr[bef_root])``        ``|| (arr[root] < arr[bef_root]``            ``&& arr[bbef_root] < arr[bef_root])) {``        ``return` `arr[bef_root] + maxSum[bbef_root];``    ``}` `    ``// case (arr[bef_root] == arr[bbef_root])``    ``else` `{``        ``return` `backtracking(arr, maxSum, before, N, root,``                            ``bef_root, before[bbef_root]);``    ``}``}` `int` `maxSumAlternatingSubsequence(``int` `arr[], ``int` `N)``{` `    ``// Max alternating subsequence sum``    ``// ending at arr[i].``    ``int` `maxSum[N];` `    ``// Array to store the index of the element``    ``// preceding the last element at maxSum[i]``    ``int` `before[N];` `    ``// Value initialization for arrays:``    ``fill_n(&maxSum[0], N, 0);``    ``maxSum[0] = arr[0];``    ``before[0] = -1;` `    ``// Iterate over the array:``    ``for` `(``int` `i = 1; i < N; i++)``        ``for` `(``int` `j = 0; j < i; j++) {``            ``int` `currentMax = 0;``            ``if` `((arr[i] > arr[j]``                 ``&& arr[before[j]] > arr[j])``                ``|| (arr[i] < arr[j]``                    ``&& arr[before[j]] < arr[j])``                ``|| before[j] == -1) {` `                ``// Whenever an element is``                ``// between two smaller elements``                ``//  or between two larger elements,``                ``//  it is an alternating sequence.``                ``//  When the preceding index of j is -1,``                ``//  we need to treat it explicitly,``                ``// because -1 is not a valid index.``                ``currentMax = (arr[i] == arr[j])``                                 ``? maxSum[j]``                                 ``: arr[i] + maxSum[j];``            ``}``          ` `            ``else` `if` `(arr[i] == arr[j]) {``                ``// If arr[i] is equal to arr[j] then``                ``// only take it once,``                ``// before[j] cannot be equal to -1.``                ``currentMax = maxSum[j];``            ``}``          ` `            ``else` `{``                ``// Perform backtracking``                ``// If three adjacent elements``                ``// are increasing or decreasing.``                ``currentMax = arr[i]``                             ``+ backtracking(``                                 ``arr, maxSum, before, N, i,``                                 ``j, before[before[j]]);``            ``}` `            ``if` `(currentMax >= maxSum[i]) {``                ``// Stores the maximum sum and``                ``// the index preceding``                ``// the last element``                ``// at position i of``                ``// current alternating subsequence``                ``// after each iteration.``                ``maxSum[i] = currentMax;``                ``before[i] = j;``            ``}``        ``}` `    ``// get max result in array``    ``return` `*max_element(maxSum, maxSum + N);``}` `// Driver code``int` `main()``{``    ``int` `arr[] = { 1, 5, 7, 3, 4, 5 };``    ``int` `N = ``sizeof``(arr) / ``sizeof``(``int``);` `    ``// Maximum sum of alternating subsequence``    ``// of array arr[]``    ``cout << maxSumAlternatingSubsequence(arr, N)``      ``<< endl;` `    ``return` `0;``}`

## Java

 `// Java code to implement the above approach``import` `java.io.*;` `class` `GFG{` `// Function for backtracking``static` `int` `backtracking(``int` `arr[], ``int` `maxSum[],``                        ``int` `before[], ``int` `N, ``int` `root,``                        ``int` `bef_root, ``int` `bbef_root)``{``    ` `    ``// {root, bef_root} represents state{i, j}``    ``// bbef_root represent before[before[j]]``    ``// We ignore the invalid before[j] index` `    ``// Base case:``    ``if` `(bbef_root == -``1``)``        ``return` `arr[bef_root];` `    ``// The case of a subsequence with``    ``// alternating parts:``    ``if` `((arr[root] > arr[bef_root] &&``    ``arr[bbef_root] > arr[bef_root]) ||``        ``(arr[root] < arr[bef_root] &&``    ``arr[bbef_root] < arr[bef_root]))``    ``{``        ``return` `arr[bef_root] + maxSum[bbef_root];``    ``}` `    ``// case (arr[bef_root] == arr[bbef_root])``    ``else``    ``{``        ``return` `backtracking(arr, maxSum, before, N,``                            ``root, bef_root,``                            ``before[bbef_root]);``    ``}``}` `static` `int` `maxSumAlternatingSubsequence(``int` `arr[],``                                        ``int` `N)``{` `    ``// Max alternating subsequence sum``    ``// ending at arr[i].``    ``int` `maxSum[] = ``new` `int``[N];` `    ``// Array to store the index of the element``    ``// preceding the last element at maxSum[i]``    ``int` `before[] = ``new` `int``[N];` `    ``// Value initialization for arrays:``    ``maxSum[``0``] = arr[``0``];``    ``before[``0``] = -``1``;` `    ``// Iterate over the array:``    ``for``(``int` `i = ``1``; i < N; i++)``        ``for``(``int` `j = ``0``; j < i; j++)``        ``{``            ``int` `currentMax = ``0``;``            ``if` `((arr[i] > arr[j] && before[j] != -``1` `&&``                   ``arr[before[j]] > arr[j]) ||``                          ``(arr[i] < arr[j] && before[j] != -``1` `&&``                   ``arr[before[j]] < arr[j]) || before[j] == -``1``)``            ``{``                ` `                ``// Whenever an element is``                ``// between two smaller elements``                ``// or between two larger elements,``                ``// it is an alternating sequence.``                ``// When the preceding index of j is -1,``                ``// we need to treat it explicitly,``                ``// because -1 is not a valid index.``                ``currentMax = (arr[i] == arr[j]) ? maxSum[j] :``                              ``arr[i] + maxSum[j];``            ``}` `            ``else` `if` `(arr[i] == arr[j])``            ``{``                ` `                ``// If arr[i] is equal to arr[j] then``                ``// only take it once,``                ``// before[j] cannot be equal to -1.``                ``currentMax = maxSum[j];``            ``}``            ``else``            ``{``                ` `                ``// Perform backtracking``                ``// If three adjacent elements``                ``// are increasing or decreasing.``                ``currentMax = arr[i] + backtracking(arr, maxSum,``                                                   ``before, N, i, j,``                                                   ``before[before[j]]);``            ``}` `            ``if` `(currentMax >= maxSum[i])``            ``{``                ` `                ``// Stores the maximum sum and the index``                ``// preceding the last element at position``                ``// i of current alternating subsequence``                ``// after each iteration.``                ``maxSum[i] = currentMax;``                ``before[i] = j;``            ``}``        ``}` `    ``// get max result in array``    ``int` `maxi = ``0``;` `    ``for``(``int` `i = ``0``; i < N; i++)``    ``{``        ``maxi = Math.max(maxSum[i], maxi);``    ``}``    ``return` `maxi;``}` `// Driver code``public` `static` `void` `main(String[] args)``{``    ``int` `arr[] = { ``1``, ``5``, ``7``, ``3``, ``4``, ``5` `};``    ``int` `N = arr.length;` `    ``// Maximum sum of alternating subsequence``    ``// of array arr[]``    ``System.out.println(``        ``maxSumAlternatingSubsequence(arr, N));``}``}` `// This code is contributed by Potta Lokesh`

## Python3

 `# Python code to implement the above approach` `# Function for backtracking``def` `backtracking(arr, maxSum, before, N, root, bef_root, bbef_root):` `    ``# {root, bef_root} represents state{i, j}``    ``# bbef_root represent before[before[j]]``    ``# We ignore the invalid before[j] index` `    ``# Base case:``    ``if` `(bbef_root ``=``=` `-``1``):``        ``return` `arr[bef_root]` `    ``# The case of a subsequence with``    ``# alternating parts:``    ``if` `(arr[root] > arr[bef_root] ``and` `arr[bbef_root] > arr[bef_root]) ``or` `(arr[root] < arr[bef_root] ``and` `arr[bbef_root] < arr[bef_root]):``        ``return` `arr[bef_root] ``+` `maxSum[bbef_root]` `    ``# case (arr[bef_root] == arr[bbef_root])``    ``else``:``        ``return` `backtracking(arr, maxSum, before, N,``                            ``root, bef_root,``                            ``before[bbef_root])` `def` `maxSumAlternatingSubsequence(arr, N):` `    ``# Max alternating subsequence sum``    ``# ending at arr[i].``    ``maxSum ``=` `[``0``] ``*` `N` `    ``# Array to store the index of the element``    ``# preceding the last element at maxSum[i]``    ``before ``=` `[``0``] ``*` `N` `    ``# Value initialization for arrays:``    ``maxSum[``0``] ``=` `arr[``0``]``    ``before[``0``] ``=` `-``1` `    ``# Iterate over the array:``    ``for` `i ``in` `range``(N):``        ``for` `j ``in` `range``(i):``            ``currentMax ``=` `0``            ``if` `(arr[i] > arr[j] ``and` `before[j] !``=` `-``1` `and` `arr[before[j]] > arr[j]) ``or` `(arr[i] < arr[j] ``and` `before[j] !``=` `-``1` `and` `arr[before[j]] < arr[j]) ``or` `before[j] ``=``=` `-``1``:` `                ``# Whenever an element is``                ``# between two smaller elements``                ``# or between two larger elements,``                ``# it is an alternating sequence.``                ``# When the preceding index of j is -1,``                ``# we need to treat it explicitly,``                ``# because -1 is not a valid index.``                ``currentMax ``=` `maxSum[j] ``if` `(``                    ``arr[i] ``=``=` `arr[j]) ``else` `arr[i] ``+` `maxSum[j]` `            ``elif` `(arr[i] ``=``=` `arr[j]):` `                ``# If arr[i] is equal to arr[j] then``                ``# only take it once,``                ``# before[j] cannot be equal to -1.``                ``currentMax ``=` `maxSum[j]``            ``else``:` `                ``# Perform backtracking``                ``# If three adjacent elements``                ``# are increasing or decreasing.``                ``currentMax ``=` `arr[i] ``+` `backtracking(arr, maxSum,``                                                   ``before, N, i, j,``                                                   ``before[before[j]])` `            ``if` `(currentMax >``=` `maxSum[i]):` `                ``# Stores the maximum sum and the index``                ``# preceding the last element at position``                ``# i of current alternating subsequence``                ``# after each iteration.``                ``maxSum[i] ``=` `currentMax``                ``before[i] ``=` `j` `    ``# get max result in array``    ``maxi ``=` `0` `    ``for` `i ``in` `range``(N):``        ``maxi ``=` `max``(maxSum[i], maxi)``    ``return` `maxi` `# Driver code``arr ``=` `[``1``, ``5``, ``7``, ``3``, ``4``, ``5``]``N ``=` `len``(arr)` `# Maximum sum of alternating subsequence``# of array arr``print``(maxSumAlternatingSubsequence(arr, N))` `# This code is contributed by gfgking`

## C#

 `// C# program for above approach``using` `System;``class` `GFG{` `// Function for backtracking``static` `int` `backtracking(``int` `[]arr, ``int` `[]maxSum,``                        ``int` `[]before, ``int` `N, ``int` `root,``                        ``int` `bef_root, ``int` `bbef_root)``{``    ` `    ``// {root, bef_root} represents state{i, j}``    ``// bbef_root represent before[before[j]]``    ``// We ignore the invalid before[j] index` `    ``// Base case:``    ``if` `(bbef_root == -1)``        ``return` `arr[bef_root];` `    ``// The case of a subsequence with``    ``// alternating parts:``    ``if` `((arr[root] > arr[bef_root] &&``    ``arr[bbef_root] > arr[bef_root]) ||``        ``(arr[root] < arr[bef_root] &&``    ``arr[bbef_root] < arr[bef_root]))``    ``{``        ``return` `arr[bef_root] + maxSum[bbef_root];``    ``}` `    ``// case (arr[bef_root] == arr[bbef_root])``    ``else``    ``{``        ``return` `backtracking(arr, maxSum, before, N,``                            ``root, bef_root,``                            ``before[bbef_root]);``    ``}``}` `static` `int` `maxSumAlternatingSubsequence(``int` `[]arr,``                                        ``int` `N)``{` `    ``// Max alternating subsequence sum``    ``// ending at arr[i].``    ``int` `[]maxSum = ``new` `int``[N];` `    ``// Array to store the index of the element``    ``// preceding the last element at maxSum[i]``    ``int` `[]before = ``new` `int``[N];` `    ``// Value initialization for arrays:``    ``maxSum[0] = arr[0];``    ``before[0] = -1;` `    ``// Iterate over the array:``    ``for``(``int` `i = 1; i < N; i++)``        ``for``(``int` `j = 0; j < i; j++)``        ``{``            ``int` `currentMax = 0;``            ``if` `((arr[i] > arr[j] && before[j] != -1 &&``                   ``arr[before[j]] > arr[j]) ||``                          ``(arr[i] < arr[j] && before[j] != -1 &&``                   ``arr[before[j]] < arr[j]) || before[j] == -1)``            ``{``                ` `                ``// Whenever an element is``                ``// between two smaller elements``                ``// or between two larger elements,``                ``// it is an alternating sequence.``                ``// When the preceding index of j is -1,``                ``// we need to treat it explicitly,``                ``// because -1 is not a valid index.``                ``currentMax = (arr[i] == arr[j]) ? maxSum[j] :``                              ``arr[i] + maxSum[j];``            ``}` `            ``else` `if` `(arr[i] == arr[j])``            ``{``                ` `                ``// If arr[i] is equal to arr[j] then``                ``// only take it once,``                ``// before[j] cannot be equal to -1.``                ``currentMax = maxSum[j];``            ``}``            ``else``            ``{``                ` `                ``// Perform backtracking``                ``// If three adjacent elements``                ``// are increasing or decreasing.``                ``currentMax = arr[i] + backtracking(arr, maxSum,``                                                   ``before, N, i, j,``                                                   ``before[before[j]]);``            ``}` `            ``if` `(currentMax >= maxSum[i])``            ``{``                ` `                ``// Stores the maximum sum and the index``                ``// preceding the last element at position``                ``// i of current alternating subsequence``                ``// after each iteration.``                ``maxSum[i] = currentMax;``                ``before[i] = j;``            ``}``        ``}` `    ``// get max result in array``    ``int` `maxi = 0;` `    ``for``(``int` `i = 0; i < N; i++)``    ``{``        ``maxi = Math.Max(maxSum[i], maxi);``    ``}``    ``return` `maxi;``}` `// Driver Code``public` `static` `void` `Main()``{``    ``int` `[]arr = { 1, 5, 7, 3, 4, 5 };``    ``int` `N = arr.Length;` `    ``// Maximum sum of alternating subsequence``    ``// of array arr[]``    ``Console.Write(``        ``maxSumAlternatingSubsequence(arr, N));``}``}` `// This code is contributed by Samim Hossain Mondal.`

## Javascript

 ``

Output

`21`

Time Complexity: O(N2) where N is the length of the array.
Auxiliary Space: O(N)

My Personal Notes arrow_drop_up