通过考虑“状态”方法,复杂度为 O(n) 的算法是可能的。
对于每个索引i,状态对应我们可以得到的三个值:A[i]-K, A[i], A[i]+K。
然后,对于给定的索引,对于每个状态s = 0, 1, 2,我们可以计算在该状态终止的最大递增序列长度。
length[i+1][s] = 1 + max (length[i][s'], if val[i][s'] <= val[i+1][s], for s' = 0, 1, 2)
我们可以利用length[i][s]随着s的增加而增加的事实。
在实践中,如果我们只是想知道最终的最大长度,我们不需要记住所有的长度值。
这是一个简单的 C++ 实现,用于说明该算法。它只提供最大长度。
#include <iostream>
#include <vector>
#include <array>
#include <string>
struct Status {
std::array<int, 3> val;
std::array<int, 3> l_seq; // length sequences
};
int longuest_ascending_seq (const std::vector<int>& A, int K) {
int max_length = 0;
int n = A.size();
if (n == 0) return 0;
Status previous, current;
previous = {{A[0]-K, A[0]-K, A[0]-K}, {0, 0, 0}};
for (int i = 0; i < n; ++i) {
current.val = {A[i]-K, A[i], A[i] + K};
for (int j = 0; j < 3; ++j) {
int x = current.val[j];
if (x >= previous.val[2]) {
current.l_seq[j] = previous.l_seq[2] + 1;
} else if (x >= previous.val[1]) {
current.l_seq[j] = previous.l_seq[1] + 1;
} else if (x >= previous.val[0]) {
current.l_seq[j] = previous.l_seq[0] + 1;
} else {
current.l_seq[j] = 1;
}
}
if (current.l_seq[2] > max_length) max_length = current.l_seq[2];
std::swap (previous, current);
}
return max_length;
}
int main() {
std::vector<int> A = {6, 4, 3, 2, 0};
int K = 1;
auto ans = longuest_ascending_seq (A, K);
std::cout << ans << std::endl;
return 0;
}