Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.0k views
in Technique[技术] by (71.8m points)

arrays - Longest positive subarray

Array A[] contains only '1' and '-1'

Construct array B, where B[i] is the length of the longest continuous subarray starting at j and ending at i, where j < i and A[j] + .. + A[i] > 0

Obvious O(n^2) solution would be:

for (int i = 0; i < A.size(); ++i) {
    j = i-1;
    sum = A[i];
    B[i] = -1; //index which fills criteria not found
    while ( j >=0 ) {
        sum += A[j];
        if (sum > 0)
            B[i] = i - j + 1;
        --j;
    }
}

I'm looking for O(n) solution.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The trick is to realize that we only need to find the minimum j such that (A[0] + ... + A[j-1]) == (A[0] + ... + A[i]) - 1. A[j] + ... + A[i] is the the same as (A[0] + ... + A[i]) - (A[0] + ... + A[j-1]), so once we find the proper j, the sum between j and i is going to be 1. Any earlier j wouldn't produce a positive value, and any later j wouldn't give us the longest possible sequence. If we keep track of where we first reach each successive negative value, then we can easily look up the proper j for any given i.

Here is a C++ implementation:

vector<int> solve(const vector<int> &A)
{
    int n = A.size();
    int sum = 0;
    int min = 0;
    vector<int> low_points;
    low_points.push_back(-1);
    // low_points[0] is the position where we first reached a sum of 0
    // which is just before the first index.
    vector<int> B(n,-1);
    for (int i=0; i!=n; ++i) {
        sum += A[i];
        if (sum<min) {
            min = sum;
            low_points.push_back(i);
            // low_points[-sum] will be the index where the sum was first
            // reached.
        }
        else if (sum>min) {
            // Go back to where the sum was one less than what it is now,
            // or go all the way back to the beginning if the sum is
            // positive.
            int index = sum<1 ? -(sum-1) : 0;
            int length = i-low_points[index];
            if (length>1) {
                B[i] = length;
            }
        }
    }
    return B;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...