数组A []仅包含“ 1”和“ -1”
构造数组B,其中B [i]是从j开始到i为止的最长连续子数组的长度,其中 j < i and A[j] + .. + A[i] > 0
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)解决方案。
诀窍是要认识到,我们只需要找到的最小值j即可(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。
(A[0] + ... + A[j-1]) == (A[0] + ... + A[i]) - 1
A[j] + ... + A[i]
(A[0] + ... + A[i]) - (A[0] + ... + A[j-1])
这是一个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; }