这个专栏已经有26篇笔记了,竟然还没有一篇DP相关的,这篇便是第一篇。我们来看动态规划的经典问题——最长上升子序列(Longest Increasing Subsequence,LIS)。
顾名思义,我们要求序列中最长的单调增的子序列(不一定连续)的长度。很容易想到朴素的
做法:设
为以
结尾的LIS,则转移方程为
。这是一个所谓的1D/1D动态规划问题,状态数和单次转移的时间复杂度都是
。然而,它可以利用
二分优化到
,这篇文章重点就介绍
的写法。
考虑维护一个数组dp[]
及当前长度len
,dp[i]
表示长度为i的上升子序列的最后一个元素的最小值。 然后考虑如何转移:
- 现在我们有一个新元素
a
,对比dp
的最后一个元素。如果a > dp[len]
,那么可以直接把a
“接到”dp[len]
的后面, 形成更长的上升子序列。即:dp[++len] = a;
- 否则,找到
dp
中第一个大于等于a
的元素,用a
替换它 。这样替换后既保证仍形成上升子序列,又使得该上升子序列的最后元素更小。
如果你看懂了上面这些话,你可能有基础或者天赋异禀;否则,我们还是来看例子吧。
现在有序列4&#