Finding the longest non-negative sub array

前端 未结 3 872
粉色の甜心
粉色の甜心 2020-12-19 11:37

I\'m looking for an more efficient alternative to brute force for finding the longest sub array of an array with a non-negative sum. The numbers range from -5 to 5 in this a

相关标签:
3条回答
  • 2020-12-19 12:08

    This is called the "longest biased interval" and is a common problem in biology. Here is the algorithm (where in your case L==0):

    Input: A nonempty array of n real numbers `A[1 . . . n]` and a lower bound `L`.
    
    Output: The start and end index of the longest segment of `A` with sum at least `L`.
    
    C[0 . . . n] and M[0 . . . n] are arrays of size n +1, as defined in the context.
    
    M[0]←C[0]←0; x←y←0;
    for i←1 to n do
        C[i]←C[i −1] + A[i];
        if C[i −1]<C[M[i −1]] then M[i]←i −1 else M[i] = M[i −1];
        k←i −y +x − 1;
        while k >0 do
            if C[i] − C[M[k]] >= L then k←M[k] else break;
            x←k +1; y←i;
        end while
        OUTPUT A(x, y);
    end for
    

    See Chen, Kuan-Yu, and Kun-Mao Chao. "Optimal algorithms for locating the longest and shortest segments satisfying a sum or an average constraint." Information Processing Letters 96.6 (2005): 197-201.

    Here is an illustration of the concept:

    enter image description here

    0 讨论(0)
  • 2020-12-19 12:12

    you can keep track of 11 things for each element while using dynamic programming, moving from left to right. Those 11 things correspond to the following possible sum :
    -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5
    For each of these you need to store the left most index, such that sum of the subarray starting at that index and ending in the current index gives that much sum.
    This is not a complete solution, but I believe this may serve the purpose of hint.

    0 讨论(0)
  • 2020-12-19 12:13

    HINTS

    You can do this in linear time by:

    1. First compute the cumulative sum of your array A
    2. Then compute an array B giving the greatest value in A to the right of index i
    3. And compute an array C giving the smallest value in A to the left of index i

    Both B and C will be non-increasing arrays.

    Then for each start position in array C, compute the greatest end position in array B such that B[end]>C[start]. This can be done in linear time by:

    1. start with start=0
    2. increment end until B[end+1]<=C[start]
    3. increment start and return to step 2

    The greatest value of end-start corresponds to the longest subarray.

    Explanation

    The main idea is that once you have a cumulative sum of your array you can compute the value of a subarray by doing a subtraction.

    For example, the array:

    4 2 -5 3 0 -2 
    

    has cumulative values:

    A = [4 6 1 4 4 2]
    

    So to find the sum of the second, third, fourth entries (indices 1,2,3 with values 2,-5,3) we can compute:

    A[3]-A[0] = 4 - 4 = 0
    

    and so your problem now reduces to finding pairs of values in array A that are furthest apart and also have A[end]>A[start].

    0 讨论(0)
提交回复
热议问题