最长上升子序列(三)
问题简述
给定数组,返回字典序最小的最长上升子序列;
思路:动态规划
为了返回字典序最小的 LIS,本题需要结合两种 dp 状态;
记
dp_min[i]
表示长度为(i+1)
的 LIS 结尾的最小值;记
dp_len[i]
表示以arr[i]
结尾的 LIS 的长度;
这两种状态都可以用来求 LIS 的长度,前者的时间复杂度为 $O(n\log n)$,后者为 $O(n^2)$
得到这两个状态序列后就可以来计算具体的 LIS 了;下面举例说明如何使用这两个状态来还原 LIS;
arr: [1,2,8,6,4] dp_len: [1,2,3,3,3] dp_min: [1,2,4] # 这里省略了这两个状态序列的生成过程, # 因为 dp_len 可以在计算 dp_min 的过程中一起获得,因此时间复杂度依然是 `O(NlogN)` 初始化: cnt = len(dp_min) # LIS 的长度 ret = [0] * cnt # 记录 LIS 然后逆序遍历 dp_len 当 dp_len[i] == cnt 时,将 ret[cnt - 1] 赋值为 arr[i],同时 cnt -= 1 为什么要逆序遍历? 举个例子,arr 结尾的三个数,其最大的 LIS 长度都是 3,但其中 4 是最小的, 因为如果它不是最小的,意味着它对应的 LIS 长度就应该大于 3 了
Last updated