📅  最后修改于: 2023-12-03 15:10:16.563000             🧑  作者: Mango
本题涉及动态规划和最长上升子序列(LIS)的问题。
给定一个整数序列 $A=(a_1, a_2, ..., a_n)$,求其最长上升子序列长度。
$dp[i]$ 表示以 $a_i$ 结尾的最长上升子序列长度。则对于 $i<j$,若 $a_j>a_i$,则有 $dp[j]=\max(dp[j], dp[i]+1)$。
初始化 $dp[i]=1$。
最终答案为 $\max(dp[i])$。
时间复杂度 $O(n^2)$。
代码片段:
dp = [1] * n
for i in range(1, n):
for j in range(i):
if a[j] < a[i]:
dp[i] = max(dp[i], dp[j] + 1)
print(max(dp))
注意到 $dp[i]$ 只和 $dp[0...i-1]$ 有关,可以使用二分查找进行优化。
用数组 $d[i]$ 记录长度为 $i$ 的 LIS 的最小末尾元素。
对每个元素 $a_i$,若 $a_i > d[length]$,则 $length$ 自增,否则在 $d$ 的 $[1,length]$ 中二分查找最小的 $d[k]$ 满足 $a_i\le d[k]$,并令 $d[k]=a_i$。
最终返回 $length$。
时间复杂度 $O(n\log n)$。
代码片段:
length = 0
d = [0] * (n + 1)
for i in range(n):
if a[i] > d[length]:
length += 1
d[length] = a[i]
else:
pos = bisect_left(d, a[i], lo=1, hi=length)
d[pos] = a[i]
print(length)
本题可以使用动态规划或 LIS 求解。
LIS 使用了二分查找优化,时间复杂度更优。
代码中需要注意数组索引和二分查找的参数。
代码示例以 Python 为例,其他语言类似。