数组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;
}
}
Run Code Online (Sandbox Code Playgroud)
我正在寻找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 。
这是一个 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;
}
Run Code Online (Sandbox Code Playgroud)