数组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)解决方案。
答案 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开始(没关系)。
所以:在考虑任何要点时,你想要得到左边 最远的其他点, 。
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;克
您可以在同一次迭代中组合一些操作。