For example, given
A = [1,51,3,1,100,199,3], maxSum = 51 + 1 + 199 = 251.
clearly max(oddIndexSum,evenIndexSum)
does not
A recursive answer in strange Prologesque pseudocode:
maxSum([]) = 0
maxSum([x]) = x
maxSum(A) = max(A[0] + maxSum(A[2..n]),
A[1] + maxSum(A[3..n]))
With appropriate handling of out-of-range indexes.
Edit: This reduces to MarcusQ's nicer answer:
maxSum([]) = 0
maxSum(A) = max(A[0] + maxSum(A[2..n]), maxSum(A[1..n]))
Edit: Here's a version that returns the actual subsequence rather than just its sum. It stretches the limits of my ad hoc pseudo-Prolog-C Chimera, so I'll stop now.
maxSub([]) = []
maxSub(A) = sub1 = [A[0]] + maxSub(A[2..n])
sub2 = maxSub(A[1..n])
return sum(sub1) > sum(sub2) ? sub1 : sub2
To avoid recursion, we can take from reverse than forward,
ie) for Array A[1..n]->
maxSum(A,n): for all n
if n=0, maxSum = 0 else
if n=1, maxSum=A[1] else
maxSum = max(A[n] + maxSum(A,n-2), maxSum(A,n-1))
To avoid computing of Max(A,n-2), while expanding maxSum(A,n-1), it can be stored and computed. That is why I ask to reverse. ie) maxSum(A,n-1) = max(A[n-1]+ maxSum(A,n-3), maxSum(A,n-2) ) where in Max(A,n-2) is already got, and no need to recalculate ) In otherwords compute maxSum(A,n) for all n starting from 1 to n using above formula to avoid recomputing.
ie) n=2, maxSum = max(A[1]+maxSum(A,0), maxSum(A,1) ) ie) n=3, maxSum = max(A[2]+maxSum(A,2), maxSum(A,2) ) and so on .. and reach last n. this will be o(n).
Here is an answer done using dynamic programming using the same base concept as that used by MarkusQ. I am just calculating the sum, not the actual sequence, which can produced by a simple modification to this code sample. I am surprised nobody mentioned this yet, because dynamic programming seems a better approach rather than recursion + memoization !
int maxSeqSum(int *arr, int size) {
int i, a, b, c;
b = arr[0];
a = (arr[1] > arr[0]) ? arr[1]: arr[0];
for(i=2;i<size;i++) {
c = (a > (b + arr[i]))? a : (b + arr[i]);
b = a;
a = c;
}
return a;
}
MarkusQ's code appears to completely skip over a[2]. I'm not smart enough to figure out where it should figure into the reckoning.
find_max(int t, int n)
{
if(t>=n)
return 0;
int sum =0, max_sum =0;
for(int i=t; i<n; ++i)
{
sum = sum + A[i];
for(int j=i+2; j<n; ++j)
sum = sum + find_max(A[j], n);
if(sum > max_sum)
max_sum = sum;
}
return max_sum;
}
The above is a recursive solution, have not compiled it. It's fairly trivial to see the repetition and convert this to a DP. Will post that soon.
@MarkusQ's answer as a Python oneliner (modified as @recursive suggested in the comments):
f = lambda L: L and max([L[0]] + f(L[2:]), f(L[1:]), key=sum)
Example:
>>> f([1,51,3,1,100,199,3])
[51, 1, 199]
It is inefficient, but It might be used to test faster solutions.
(defun maxsubseq (L)
"Based on MarkusQ's and sth's answers."
(if (not L) L
(let ((incl (cons (car L) (maxsubseq (cddr L))))
(excl (maxsubseq (cdr L))))
(if (> (sum incl) (sum excl)) incl excl))))
(defun sum (L) (apply '+ L))
It is based on @sth's answer:
(defun maxsubseq-iter-impl (L excl incl) (let ((next (if (> (car excl) (car incl)) excl incl)) (x (car L))) (if (not L) (cdr next) (maxsubseq-iter-impl (cdr L) next (cons (+ x (car excl)) (cons x (cdr excl))))))) (defun maxsubseq-iter (L) (reverse (maxsubseq-iter-impl L '(0) '(0))))
(require 'cl) (loop for f in '(maxsubseq maxsubseq-iter) collect (loop for L in '((1 51 3 1 100 199 3) (9 10 9)) collect (f L)))
Output:
(((51 1 199) (9 9)) ((51 1 199) (9 9)))