Reputation: 3331
Given an array of integers, what is the maximum sum of a subset of the integers such that the integers in the subset were not originally next to each other?
Examples:
[3, 8, 4] => max sum is 8, since 8 > (3+4)
[12, 8, 9, 10] => max sum is 12 + 10 = 22, since this is greater than 12 + 9 and 8 + 10
I'm interested in figuring out the algorithm for doing this. Methodology / thinking process = greatly appreciated.
EDIT: The integers range from 1 to 1000, inclusive. (Since this is entirely a learning exercise, I'd still be interested in learning about different methods if the integers ranged from, say, -1000 to 1000.)
Upvotes: 1
Views: 4722
Reputation: 1769
Let you have array A {Ai, 1 <= i <= n }
F(i)
- Maximum sum of subarray Aj { 1 <= j <= i }
, then
F(0) = 0
- empty subarray
F(1) = A(1)
- only first element
F(i) = max(F(i-2) + A(i), F(i-1)) , 2 <= i <= n
F(n)
- answer
C++ implementation:
int GetMaximumSubarraySum(const vector<int>& a)
{
// note that vector a have 1-based index
vector<int> v(a.size());
v[0] = 0;
v[1] = a[1];
for(int i =2; i < a.size(); i++)
v[i] = max(v[i-2] + a[i], v[i-1]);
return v.back();
}
Explanation:
First, main idea is to use dynamic programming.
We try to solve task for array with N element by using known answer for array with N-1
and N-2
first elements. If N = 0
the answer is 0
and if N = 1
the answer is A[1]
. It's clear. For N >= 2
we have 2 different ways:
Use element A[N],
then the answer is A[N] + F[N-2]
(because we can't use A[N-1] element and F[N-2]
is the best solution for subarray 1..N-2
, we don't care about if F[N-2]
element is used or not, this is just the best solution for subarray 1..N-2
.
Don't use element A[N]
, then the answer is F[N-1]
(because we can use A[N-1] element and F[N-1]
is the best solution for subarray 1..N-1
, also we don't care about if F[N-1]
element is used or not.
So we need to get max of this 2 situations.
To solve the task you need calculate F[N]
in increasing order and memorize answers.
Let see at your example:
[12, 8, 9, 10]
F[0] = 0
F[1] = 12
- use 1-st element
F[2] = max(F[0]+A[2], F[1]) = max(8, 12) = 12
- use 1-st element
F[3] = max(F[1]+A[3], F[2]) = max(21, 12) = 21
- use 1-st, 3-rd element
F[4] = max(F[2]+A[4], F[3]) = max(22, 21) = 22
- use 1-st, 4-th element
The answer is F[4] = 22
.
Upvotes: 9
Reputation: 19621
The only uniformly successful thinking process I know is to have seen the problem before. Looking at your question my first thought was "I need to maximise a sum subject to what seems to be a set of fairly simple boolean constraints". In Knuth Vol 4A section 7.1.4 Algorithm B Knuth describes how to solve such a problem, as long as the constraints can be expressed as a http://en.wikipedia.org/wiki/Binary_decision_diagram of manageable size. If you already have a BDD package, you can therefore solve a whole class of problems of this type just by constructing a BDD that describes your particular constraints.
My second thought was to note that later on in the same section, Knuth shows connections between BDDs and linear networks of boolean logic. Given this, there should be a tractable dynamic programming solution to your problem. If you are looking for a general methodology to learn, dynamic programming is a pretty good candidate. In this case it seems to lead to an algorithm pretty much like that presented by Ivan Benko, although he seems to be working under the assumption - supported by your example data - that the integers are all >= 0, and it could work for general integers with a few more if statements.
Upvotes: 2
Reputation: 12373
Here is a solution know as the kadane's Alogithme
Algorithm 1 Kadane’s algorithm
M ← 0, t ← 0
i ← 1
for j ← 1 to n do
t ← t + a[j]
if t > M then M ← t, (x1 , x2 ) ← (i, j)
if t ≤ 0 then t ← 0, i ← j + 1// reset the accumulation
end for
output M , (x1 , x2 )
Upvotes: 0
Reputation: 80287
Think recursively: Best result is maximum from cases- to use first element (first in recursion branch) or not to use it in sum
Best(i) = Max(A[i] + Best(i + 2), Best(i + 1))
Upvotes: 0