问题描述:
输入数组 A[0:n]和正实数 d,试设计一个动态规划算法输出 A[0:n]的一个最长子序列,使得子序列中相继元素之差的绝对值不超过 d。分析算法的时间复杂度。
这个问题刚开始拿到没啥思路,一直想不到这个问题的最优子结构,后来看到了最长递增子序列问题的解,发现这个问题和最长递增子序列问题的思路类似。
我们来回忆一下最长递增子序列问题,我们在处理这个问题的时候可以进行一些适当的转换。尽管题目要求求A[0:n]的最长递增子序列,但是因为每个序列都有一个处在最后的元素,因此可以转换为求以某个元素结尾的最长递增子序列问题,最后只要一个O(n)的遍历就能得到最长递增子序列了。这么转换的好处是最优子结构一目了然,比如说我们找到了一个最长递增子序列b1b2...bn,那么显然,b1...bn-1为a0....bn-1的最长递增子序列,因为如果不是,那么将更长的和bn组合起来,就得到了一个比b1...bn还长的序列,这与我们的假设矛盾。在找到了最优子结构以后,很容易的可以写出递归式:
设list[i]存储的为以A[i]结尾的最长递增子序列,那么list[i]=max{list[j]}+1(其中j<i,且A[i]>A[j])如果不存在A[j]那么list[i]=1.
这个算法很简单就能写出来了。
而回过头看这个题,其实并没有啥区别。一个序列a1a2a3...an的最长这个子序列为b1b2b3...bk,那么显然,b1....bk-1是以bk-1结尾的最长这个子序列,证明方法还是复制剪切法。所以我们很容易的可以得到一个递归式:
设dis[i]保存的是以A[i]结尾的最长的这个子序列的长度,那么dis[i]=max{dis[j]}+1 其中j<i且要求满足A[j]与A[i]的差的绝对值小于d.
得到了递归式以后,我们很容易可以得到动态规划算法。
当然,最后还要遍历一下dis数组求出最大值。