Maximum sum bitonic subarray

Given an array containing n numbers. The problem is to find the maximum sum bitonic subarray. A bitonic subarray is a subarray in which elements are first increasing and then decreasing. A strictly increasing or strictly decreasing subarray is also considered as bitonic subarray. Time Complexity of O(n) is required.

Examples:

```Input : arr[] = {5, 3, 9, 2, 7, 6, 4}
Output : 19
The subarray is {2, 7, 6, 4}.

Input : arr[] = {9, 12, 14, 8, 6, 5, 10, 20}
Output : 54
```

Recommended: Please solve it on “PRACTICE ” first, before moving on to the solution.

Approach: The problem is closely related to Maximum Sum Bitonic Subsequence. We create two arrays msis[] and msds[]. msis[i] stores the sum of Increasing subarray ending with arr[i]. msds[i] stores the sum of Decreasing subarray starting from arr[i]. Now, maximum sum bitonic subarray is calculated as max(msis[i]+msds[i]-arr[i]) for each index i of the array.

```// C++ implementation to find the
// maximum sum bitonic subarray
#include <bits/stdc++.h>

using namespace std;

// function to find the maximum sum
// bitonic subarray
int maxSumBitonicSubArr(int arr[], int n)
{
// 'msis[]' to store the maximum sum increasing subarray
// up to each index of 'arr' from the beginning
// 'msds[]' to store the maximum sum decreasing subarray
// from each index of 'arr' up to the end
int msis[n], msds[n];

// to store the maximum sum
// bitonic subarray
int max_sum = INT_MIN;

// building up the maximum sum increasing subarray
// for each array index
msis[0] = arr[0];
for (int i=1; i<n; i++)
if (arr[i] > arr[i-1])
msis[i] = msis[i-1] + arr[i];
else
msis[i] = arr[i];

// building up the maximum sum decreasing subarray
// for each array index
msds[n-1] = arr[n-1];
for (int i=n-2; i>=0; i--)
if (arr[i] > arr[i+1])
msds[i] = msds[i+1] + arr[i];
else
msds[i] = arr[i];

// for each array index, calculating the maximum sum
// of bitonic subarray of which it is a part of
for (int i=0; i<n; i++)
// if true , then update 'max' bitonic
// subarray sum
if (max_sum < (msis[i] + msds[i] - arr[i]))
max_sum = msis[i] + msds[i] - arr[i];

// required maximum sum
return max_sum;
}

// Driver program to test above
int main()
{
int arr[] = {5, 3, 9, 2, 7, 6, 4};
int n = sizeof(arr) / sizeof(arr[0]);
cout << "Maximum Sum = "
<< maxSumBitonicSubArr(arr, n);
return 0;
}
```

Output:

```Maximum Sum = 19
```

Time Complexity: O(n)
Auxiliary Space: O(n)

Space optimized solution:
It can be solved with constant memory. Indeed, since we are looking for contiguous subarrays, we can separate the initial array into bitonic chunks and compare their sums.

```// C++ implementation to find the
// maximum sum bitonic subarray
#include <bits/stdc++.h>
using namespace std;

// Function to find the maximum sum bitonic
// subarray.
int maxSumBitonicSubArr(int arr[], int n)
{
// to store the maximum sum
// bitonic subarray
int max_sum = INT_MIN;

int i = 0;
while (i < n) {

// Find the longest increasing subarray
// starting at i.
int j = i;
while (j+1 < n && arr[j] < arr[j+1])
j++;

// Now we know that a[i..j] is an
// increasing subarray. Remove non-
// positive elements from the left
// side as much as possible.
while (i < j && arr[i] <= 0)
i++;

// Find the longest decreasing subarray
// starting at j.
int k = j;
while (k+1 < n && arr[k] > arr[k+1])
k++;

// Now we know that a[j..k] is a
// decreasing subarray. Remove non-
// positive elements from the right
// side as much as possible.
// last is needed to keep the last
// seen element.
int last = k;
while (k > j && arr[k] <= 0)
k--;

// Compute the max sum of the
// increasing part.
int sum_inc =
accumulate(arr+i, arr+j+1, 0);

// Compute the max sum of the
// decreasing part.
int sum_dec =
accumulate(arr+j, arr+k+1, 0);

// The overall max sum is the sum of
// both parts minus the peak element,
// because it was counted twice.
int sum_all = sum_inc + sum_dec - arr[j];

max_sum = max({max_sum, sum_inc,
sum_dec, sum_all});

// If the next element is equal to the
// current, i.e. arr[i+1] == arr[i],
// last == i.
// To ensure the algorithm has progress,
// get the max of last and i+1.
i = max(last, i+1);
}

// required maximum sum
return max_sum;
}

// Driver program to test above
int main()
{
// The example from the article, the
int arr[] = {5, 3, 9, 2, 7, 6, 4};
int n = sizeof(arr) / sizeof(arr[0]);
cout << "Maximum Sum = "
<< maxSumBitonicSubArr(arr, n)
<< endl;

// Always increasing, the answer is 15.
int arr2[] = {1, 2, 3, 4, 5};
int n2 = sizeof(arr2) / sizeof(arr2[0]);
cout << "Maximum Sum = "
<< maxSumBitonicSubArr(arr2, n2)
<< endl;

// Always decreasing, the answer is 15.
int arr3[] = {5, 4, 3, 2, 1};
int n3 = sizeof(arr3) / sizeof(arr3[0]);
cout << "Maximum Sum = "
<< maxSumBitonicSubArr(arr3, n3)
<< endl;

// All are equal, the answer is 5.
int arr4[] = {5, 5, 5, 5};
int n4 = sizeof(arr4) / sizeof(arr4[0]);
cout << "Maximum Sum = "
<< maxSumBitonicSubArr(arr4, n4)
<< endl;

// The whole array is bitonic, but the answer is 7.
int arr5[] = {-1, 0, 1, 2, 3, 1, 0, -1, -10};
int n5 = sizeof(arr5) / sizeof(arr5[0]);
cout << "Maximum Sum = "
<< maxSumBitonicSubArr(arr5, n5)
<< endl;

// The answer is 4 (the tail).
int arr6[] = {-1, 0, 1, 2, 0, -1, -2, 0, 1, 3};
int n6 = sizeof(arr6) / sizeof(arr6[0]);
cout << "Maximum Sum = "
<< maxSumBitonicSubArr(arr6, n6)
<< endl;

return 0;
}
```

Output:

```Maximum Sum = 19
Maximum Sum = 15
Maximum Sum = 15
Maximum Sum = 5
Maximum Sum = 7
Maximum Sum = 4

```

Thanks to Andrey Khayrutdinov for suggesting this solution.

This article is contributed by Ayush Jauhari. If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

GATE CS Corner    Company Wise Coding Practice

Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.
2.6 Average Difficulty : 2.6/5.0
Based on 3 vote(s)