You are given a 0-indexed array vect of n integers. You need to perform the following 2 operations exactly once-
- Choose an index
i{0, 1, 2, ..., n-1} and multiply the entire prefix segment {0..i} by -1. - Choose an index
j{0, 1, 2, ..., n-1} and multiply the entire suffix segment {j...n-1} by -1.
Choosing i and j, we need to maximize the entire sum of all elements of the array.
Note:
It is possible for the prefix and suffix segments to overlap, i.e. when i = j or i > j. As expected, when a sub-segment undergoes both operations, it's value remains unchanged.
Approach:
- Make the array 1-based and calculate the prefix
prefand suffixsuffsums. - While calculating the maximum sum at any index
iandjwherei < j, we have
sum = (-1)*pref[i] + Z + (-1)*suff[j]
Z can be calculated aspref[j-1] - pref[(i+1)-1].Z = {}whenj - i = 1. - We can only have
j > ias overlapping sub-segments would remain the same and have no effect on the final answer. - Iterate for different values of
iandj.
Time Complexity - O(n^2)
Observations
- If none of the elements in
prefis negative, we can only negatepref[1]to reduce the maximum sum as little as possible. Similarly, forsuffwe can dosuff[n]. - If atleast one of the elements in both
prefandsuffis negative, lets saypref[i] < 0andsuff[j] < 0, our maximum answer will always involve negatingpref[i]orsuff[j]or both ifi < j.
We can do slight optimizations using the above observations, but it would not change the Time Complexity (a case where all elements in vect are negative, leading to pref and suff have all negative elements).
Code (in C++)
using ll = long long;
ll getMaxInvSum(vector<int> vect) {
int n = vect.size();
vector<ll> pref(n+2), suff(n+2); // add dummy element at the front and back of vect
pref[0] = 0;
for(int i=0; i<n; i++) pref[i+1] = pref[i] + vect[i];
pref[n+1] = pref[n];
suff[n+1] = 0;
for(int j=n-1; j>=0; j--) suff[j+1] = suff[j+2] + vect[j];
suff[0] = suff[1];
ll ans = pref[n]; // pref[n+1], suff[0], suff[1]
for(int i=1; i<n; i++) {
for(int j=i+1; j<=n; j++) {
if(j-i == 1)
ans = max(ans, pref[i]*(-1) + suff[j]*(-1));
else
ans = max(ans, pref[i]*(-1) + suff[j]*(-1) + pref[j-1] - pref[i+1-1]);
}
}
return ans;
}
How can I improve on the Time Complexity ?
Let me show the algorithmic solution (
O(n)time complexity), while skipping its implementation.First of all, we can state the problem in a different way: we don't let overlapping, e.g.
which equals to
but we allow empty prefixes and suffixes instead:
So we can solve the problem in linear time: find the best prefix by using rolling sums (best prefix must have negative minimum sum):
similar we can compute the suffix (we compute sums staring from the end in this case):
If best prefix and best suffix don't overlap, return them as an answer. If prefix and suffix overlap, we should choose between two options:
In the example above:
1, 2, 3, -9, -8prefix and-1suffix, we have 19-9 -8 3 4 -1suffix, we have 17So far so good, we choose 1st option (
19) which is