最长的正面子阵列

时间:2016-01-10 04:01:24

标签: arrays algorithm

数组A []仅包含' 1'和' -1'

构造数组B,其中B [i]是从j开始到i结束的最长连续子阵列的长度,其中j < i and A[j] + .. + A[i] > 0

明显的O(n ^ 2)解决方案是:

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;
    }
}

我正在寻找O(n)解决方案。

2 个答案:

答案 0 :(得分:2)

诀窍是要意识到我们只需找到(A[0] + ... + A[j-1]) == (A[0] + ... + A[i]) - 1的最小值。 A[j] + ... + A[i](A[0] + ... + A[i]) - (A[0] + ... + A[j-1])相同,因此一旦找到正确的j,j和i之间的总和将为1。 任何早期的j都不会产生正值,任何后来的j都不会给我们最长的序列。如果我们跟踪我们首先达到每个连续负值的位置,那么我们可以轻松地查找任何给定i的正确j。

这是一个C ++实现:

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;
}

答案 1 :(得分:2)

你可以考虑+ 1 / -1之和,就像我的图表一样。我们从0开始(没关系)。

representation of sums of +1/-1

所以:在考虑任何要点时,你想要得到左边 最远的其他点,

1构造并保持总和

需要n次迭代:O(n)

2构建一个表值=&gt;指向,迭代每个点,并保持最左边的位置:

你得到:0 =&gt; a,1 =&gt; b(不是d),2 =&gt; c(不是e,i,k),3 =&gt; f(不是h),4 =&gt; g(不是m),5 =&gt; n,6 =&gt; Ø

需要n次迭代:O(n)

每个级别

3(比如0,1,2,3 ......)=&gt;你保持最远点,低于它:

等级0 =&gt;一个

等级1 =&gt;一个

等。 =&GT;它将永远是一个。

假设图表从点g开始:

4 =&gt;克

3 =&gt; ħ

2 =&gt;我

5 =&gt;克

6 =&gt;克

然后:如果一个点刚刚超过3(那么4:作为m)=&gt;它将是h

它还需要n次操作(精确的图形高度)。

4迭代每一点:你的B [i]。

在每一点上,比如说h:sum = 3,你在它下面最远处(操作表3):在我的模式中它总是a = 0;

假设图表从点g开始:

获得积分

g,h,i,k =&gt;没有

j =&gt;我

l =&gt;我

m =&gt; ħ

n =&gt;克

您可以在同一次迭代中组合一些操作。