开发者

Maximum Countiguous Negative Sum or Mnimum positive subsequence sum problem

We all heard of bentley's beautiful proramming pearls problem which solves maximum 开发者_开发知识库subsequence sum:

maxsofar = 0;
maxcur = 0;
for (i = 0; i < n; i++) {
  maxcur = max(A[i] + maxcur, 0);
  maxsofar = max(maxsofar, maxcur);
}

What if we add an additional condition maximum subsequence that is lesser M?


This should do this. Am I wright?

int maxsofar = 0;
for (int i = 0; i < n - 1; i++) {
   int maxcur = 0;
   for (int j = i; j < n; j++) {
      maxcur = max(A[j] + maxcur, 0);
      maxsofar = maxcur < M ? max(maxsofar, maxcur) : maxsofar;
   }
}

Unfortunately this is O(n^2). You may speed it up a little bit by breaking the inner loop when maxcur >=M, but still n^2 remains.


This can be solved using dynamic programming albeit only in pseudo-polynomial time.

Define

m(i,s) := maximum sum less than s obtainable using only the first i elements

Then you can calculate max(n,M) using the following recurrence relation

m(i,s) = max(m(i-1,s), m(i-1,s-A[i]]+A[i]))

This solution is similar to the solution to the knapsack problem.


If all A[i] > 0, you can do this in O(n lg n): precompute partial sums S[i], then binary search S for S[i] + M. For instance:

def binary_search(L, x):
  def _binary_search(lo, hi):
    if lo >= hi: return lo
    mid = lo + (hi-lo)/2
    if x < L[mid]:
      return _binary_search(lo, mid)
    return _binary_search(mid+1, hi)
  return _binary_search(0, len(L))

A = [1, 2, 3, 2, 1]
M = 4
S = [A[0]]
for a in A[1:]:
  S.append(S[-1] + a)
maxsum = 0
for i, s in enumerate(S):
  j = binary_search(S, s + M)
  if j == len(S):
    break
  sum = S[j-1] - S[i]
  maxsum = max(sum, maxsum)
print maxsum

EDIT: as atuls correctly points out, the binary search is overkill; since S is increasing, we can just keep track of j each iteration and advance from there.


Solveable in O(n log(n)). Using a binary search tree (balanced) to search for smallest value larger than sum-M, and then update min, and insert sum, by going from left to right. Where sum is the partial sum so far.

  best = -infinity;
  sum = 0;
  tree.insert(0);
  for(i = 0; i < n; i++) {
     sum = sum + A[i];
     int diff = sum - tree.find_smallest_value_larger_than(sum - M);
     if (diff > best) {
       best = diff;
     }
     tree.insert(sum);
   }

   print best
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜