编程之美 set 7 求数组中的最长递增子序列
解法
1. 假设在目标数组 array[] 的前 i 个元素中, 最长递增子序列的长度为 LIS[i]
那么状态转移方程为
LIS[i] = max(1, LIS[k]+1) array[i+1] > array[k], for any k <= i
按照这个动规的思路, 每次求 LIS[i] 是都要遍历 LIS[0] ~ LIS[i]
时间复杂度为 o(n^2)
2. (1) 是一个比较一般性的解法. 考虑下面一个例子
目标序列为 1, -1, 2, -3, 4, -5, 6, 当 i = 4 时, 最长的递增序列是 (1,2), (-1,2) 那么 4 > 2, 就可以直接把 4 加到前面的子序列中形成一个新的递增子序列
受此启发, 我们希望找到前 i 个元素中的一个递增子序列, 使得这个递增子序列的最大元素比 array[i+1] 要小, 且长度尽可能的长. 这样将 array[i+1] 加在该递增子序列后, 便可找到以 array[i+1] 为最大元素的最长递增子序列
长度为 1 的递增子序列最大元素的最小值为 MAXV[1] (最大元素是指长度为 i 的序列中最后一个元素, 最小值是指满足长度为 i 的所有序列中第 i 个值最小的那个)
...
长度为 LIS[i] 的递增子序列最大元素的最小值为 MAXV[LIS[i]]
假如有了这些值, 那么可以倒序的查找, 更新
MAXV[] 是一个递增数组, 可以使用二分查找法, 因此时间复杂度降低到 NlogN