Algorithm to find the maximum subsequence of an array of positive numbers . Catch : No adjacent elements allowed

前端 未结 13 1121
甜味超标
甜味超标 2020-12-24 04:42

For example, given

A = [1,51,3,1,100,199,3], maxSum = 51 + 1 + 199 = 251.

clearly max(oddIndexSum,evenIndexSum) does not

相关标签:
13条回答
  • 2020-12-24 05:04

    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
    
    0 讨论(0)
  • 2020-12-24 05:04

    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).

    0 讨论(0)
  • 2020-12-24 05:07

    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;
    }
    
    0 讨论(0)
  • 2020-12-24 05:07

    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.

    0 讨论(0)
  • 2020-12-24 05:11
    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.

    0 讨论(0)
  • 2020-12-24 05:11

    @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.

    Same -- in Emacs Lisp

    (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))
    

    Iterative version (O(N) if tail-recursion is available)

    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))))
    

    Example:

    (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)))
    
    0 讨论(0)
提交回复
热议问题