给定一个数组,我们需要找到具有交替递增和递减值的最长子序列的长度。
例如,如果数组是,
7 4 8 9 3 5 2 1
然后L = 6
或7,4,8,3,5,2
等7,4,9,3,5,1
也可能是首先我们有小而大的元素。
对此最有效的解决方案是什么?我有一个DP解决方案。如果我们使用蛮力来做这件事我们会怎么做(O(n ^ 3)?)?
这不是一个家庭作业问题。
答案 0 :(得分:14)
你确实可以在这里使用动态编程方法。为简单起见,假设我们只需要找到这样的序列的最大长度 seq (很容易调整解决方案以找到序列本身)。
对于每个索引,我们将存储2个值:
根据定义,我们假设incr[0] = decr[0] = 1
然后可以递归地找到每个incr [i]:
incr[i] = max(decr[j])+1, where j < i and seq[j] < seq[i]
decr[i] = max(incr[j])+1, where j < i and seq[j] > seq[i]
序列的所需长度将是两个数组中的最大值,此方法的复杂度为O(N * N),并且它需要2N的额外内存(其中N是初始序列的长度)
c中的简单示例:
int seq[N]; // initial sequence
int incr[N], decr[N];
... // Init sequences, fill incr and decr with 1's as initial values
for (int i = 1; i < N; ++i){
for (int j = 0; j < i; ++j){
if (seq[j] < seq[i])
{
// handle "increasing" step - need to check previous "decreasing" value
if (decr[j]+1 > incr[i]) incr[i] = decr[j] + 1;
}
if (seq[j] > seq[i])
{
if (incr[j]+1 > decr[i]) decr[i] = incr[j] + 1;
}
}
}
... // Now all arrays are filled, iterate over them and find maximum value
算法如何运作:
第0步(初始值):
seq = 7 4 8 9 3 5 2 1
incr = 1 1 1 1 1 1 1 1
decr = 1 1 1 1 1 1 1 1
第1步在索引1('4')处获取值并检查以前的值。 7> 4所以我们做“从索引0到索引1的减少步骤,新的序列值:
incr = 1 1 1 1 1 1 1 1
decr = 1 2 1 1 1 1 1 1
第2步。取值8并迭代以前的值:
7&lt; 8,增加步骤:incr [2] = MAX(incr [2],decr [0] +1):
incr = 1 1 2 1 1 1 1 1
decr = 1 2 1 1 1 1 1 1
4&lt; 8,增加步骤:incr [2] = MAX(incr [2],decr [1] +1):
incr = 1 1 3 1 1 1 1 1
decr = 1 2 1 1 1 1 1 1
等...