The basic idea is keeping memory of the higher sum already reached and increasing a current sum. If the current sum gets higher than the historical one, also that one is increased.
This is a first version, that calculates just the sum:
typedef std::vector<int> Vector;
int maxSubAr(const Vector& data)
{
int sum = 0;
int sumTmp = 0;
for(unsigned i = 0; i < data.size(); ++i)
{
if(int value = sumTmp + data[i] > 0) // 1
sumTmp = value;
else
sumTmp = 0;
if(sumTmp > sum) // 2
sum = sumTmp;
}
return sum;
}
1. Add the current element value to the temporary sum. If this leads to a positive number, this will be the new temporary sum, otherwise I reset it.2. If the temporary sum is bigger than the previously saved sum, I save this new value.
And that's it. Incredibly simple and effective.
Things get a bit more complicated when we want to get also the first-last index of the subsequence:
typedef std::array<int, 3> Info;
typedef std::vector<int> Vector;
Info maxSubArray(const Vector& data)
{
int left = 0;
int right = 0;
int sum = 0;
int leftTmp = 0;
int sumTmp = 0;
for(unsigned i = 0; i < data.size(); ++i)
{
int value = sumTmp + data[i];
if(value > 0)
{
if(sumTmp == 0) // 1
leftTmp = i;
sumTmp = value;
}
else
sumTmp = 0;
if(sumTmp > sum) // 2
{
left = leftTmp;
right = i;
sum = sumTmp;
}
}
return {{ left, right, sum }};
}
1. If I am at the beginning of the sequence, or if I have just reset the temporary sum, the current value is at the tentative first element of the subsequence.2. When I see that the current sum is bigger than the one already discovered, I adjust also the left/right indexes.
Full C++11 code is on github, with a few GoogleTest test as a bonus.