我想知道如何才能获得序列中最长的正和子序列:
例如,我有-6 3 -4 4 -5,因此最长的正子序列是3 -44。实际上,总和为正(3),我们既不能将-6也不能相加-5,否则它将变成消极的。
它可以很容易地在O(N ^ 2)中解决,我认为它可以更快地存在,例如在O(NlogN)中
你有什么主意吗?
编辑:必须保留顺序,并且您可以从子字符串中跳过任何数字
EDIT2:很抱歉,如果我使用“sebsequence”一词引起困惑,正如@beaker指出的那样,我的意思是子字符串
最佳答案
O(n)
时空解决方案,将从代码(对不起,Java ;-)开始,并在稍后尝试进行解释:
public static int[] longestSubarray(int[] inp) {
// array containing prefix sums up to a certain index i
int[] p = new int[inp.length];
p[0] = inp[0];
for (int i = 1; i < inp.length; i++) {
p[i] = p[i - 1] + inp[i];
}
// array Q from the description below
int[] q = new int[inp.length];
q[inp.length - 1] = p[inp.length - 1];
for (int i = inp.length - 2; i >= 0; i--) {
q[i] = Math.max(q[i + 1], p[i]);
}
int a = 0;
int b = 0;
int maxLen = 0;
int curr;
int[] res = new int[] {-1,-1};
while (b < inp.length) {
curr = a > 0 ? q[b] - p[a-1] : q[b];
if (curr >= 0) {
if(b-a > maxLen) {
maxLen = b-a;
res = new int[] {a,b};
}
b++;
} else {
a++;
}
}
return res;
}
A
n
进行操作P
数组为包含前缀和的数组,直到索引i
为止,这样P[i] = sum(0,i)
其中`i = 0,1,...,n-1'u < v
和P[u] <= P[v]
,那么u
将永远不是我们的终点Q
数组,该数组具有Q[n-1] = P[n-1]
和Q[i] = max(P[i], Q[i+1])
M_{a,b}
,它向我们显示了从a
开始到b
或之后的最大和子数组。我们知道M_{0,b} = Q[b]
和M_{a,b} = Q[b] - P[a-1]
a, b = 0
并开始移动它们。如果M
的当前值大于或等于0,那么我们知道我们将找到(或已经找到)sum> = 0的子数组,那么我们只需要将b-a
与先前找到的长度进行比较即可。否则,没有子数组以a
开头并遵守我们的约束,因此我们需要增加a
。 关于algorithm - 最长正和子串,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28356453/