【发布时间】:2015-10-06 08:36:38
【问题描述】:
给定一个包含 n 个正整数的数组 arr[0 … n-1],如果 arr[] 的子序列先递增,然后递减,则称为双调。编写一个以数组为参数并返回最长双音子序列长度的函数。
输入 arr[] = {1, 11, 2, 10, 4, 5, 2, 1}; 输出:6(长度为 6 的最长双调子序列为 1、2、10、4、2、1)
现在,为了找出长度,我首先计算 LIS(Longest Inc. Subsequence)的长度,然后计算 LDS(Longest Dec. Subsequence)的长度,然后遍历这两个数组,同时执行max(lis[i] + lds[i]-1)其中i varies from 0 to (n-1)。
for ( i = 0; i < n; i++ ) // Code for LIS
{
for ( j = 0; j < i; j++ )
{
if (arr[i] > arr[j] && lis[i] < lis[j] + 1)
lis[i] = lis[j] + 1;
}
}
for ( i = 0; i < n; i++ ) // Code for LDS
{
for ( j = 0; j < i; j++ )
{
if (arr[i] < arr[j] && lds[i] < lds[j] + 1)
lds[i] = lds[j] + 1;
}
}
现在,如果我被要求打印实际的双音子序列,我该怎么做?我想到的一种方法是找出最大值出现的索引。现在,我知道该索引处的 LIS 和 LDS 的值,然后,我从该索引打印 LIS 和 LDS。但是,我无法真正正确地制定这个想法。
【问题讨论】:
-
你不应该从后面计算LDS作为LIS吗?否则,我怀疑
max(lis[i] + lds[i]-1)是否正确。无论如何,如果您更新lis[i]或lds[i],您还可以更新指向前一个元素的指针(lisPointer[i] = j)。然后你可以从兴趣点遍历这条链。 -
不,不知何故,当我从前面计算
lds时,它给出了lds[i] + lis[i] - 1的正确答案。虽然,直觉上,它应该从后面计算,但不知何故,它给出了正确的值。 -
@JohnLui 巧合的是,你得到了正确的结果:在值
5的位置,lis是 4,lds是 3,所以你得到4+3-1=6。但是,很容易构建一个示例,该解决方案会产生错误结果:{1, 2, 3, 2, 1}应该返回 5,但它会返回 3。