最长递增子序列(Longest Increasing Subsequence)
需积分: 13 190 浏览量
更新于2024-12-24
收藏 12KB TXT 举报
"这篇文章主要介绍了什么是最长递增子序列,并提供了两种不同的算法实现:动态规划和二分查找优化的动态规划。"
最长递增子序列(Longest Increasing Subsequence,LIS)是序列中一个特殊的子序列,它满足子序列中的元素严格递增,且长度尽可能长。例如,在序列 L=<a1, a2, ..., an> 中,如果存在子序列 Lin=<aK1, ak2, ..., akm>,满足 k1 < k2 < ... < km 且 aK1 < ak2 < ... < akm,那么 Lin 就是一个递增子序列。目标是找到这样的子序列,使得 m 的值最大。
解决这个问题,可以采用以下两种方法:
1. 动态规划(Dynamic Programming,DP)方法:
动态规划是一种将大问题分解为小问题来求解的方法。对于LIS问题,我们可以创建一个数组 b[n],其中 b[i] 表示以 a[i] 结尾的最长递增子序列的长度。初始化 b[0] = 1,然后对于每个 i (1 <= i < n),遍历所有小于 i 的 j (0 <= j < i),如果 a[i] > a[j] 且 b[j] + 1 > b[i],则更新 b[i] = b[j] + 1。最后,数组 b 中的最大值即为最长递增子序列的长度。这种方法的时间复杂度为 O(n^2)。
示例代码:
```cpp
int getMaxLen(int* sel, int N) {
int n1 = 1, n2 = 1, i1 = 0, i2 = 0;
for (int i = 1; i < N; i++) {
if (sel[i] > sel[i - 1]) {
n2++;
if (n2 > n1) n1 = n2;
} else
n2 = 1;
}
return n1;
}
```
2. 二分查找优化的动态规划(Binary Search Enhanced Dynamic Programming):
这种方法利用了二分查找来优化动态规划的过程。在每次更新 b[i] 时,我们可以使用二分查找来找到合适的位置,这样可以减少比较次数,从而降低时间复杂度到 O(n log n)。首先计算出所有以 a[i] 结尾的子序列长度,然后在更新 b[i] 时,通过二分查找找到 b[j] 的位置,使得 a[j] < a[i],并更新 b[i] = max(b[j] + 1, b[i])。
示例代码:
```cpp
int find(int* a, int len, int n) {
int left = 0, right = len, mid = (left + right) / 2;
while (left < right) {
// ...
}
}
int main() {
// ...
for (int i = 1; i < n; i++) {
b[i] = 1;
int index = find(a, i, a[i]);
if (index != 0 && a[index - 1] < a[i]) {
b[i] = b[index - 1] + 1;
}
}
// ...
}
```
这两种方法各有优缺点,动态规划方法简单直观,但时间复杂度较高;而二分查找优化的动态规划方法虽然实现稍微复杂,但效率更高。在实际应用中,根据具体需求和数据规模可以选择合适的方法。
3062 浏览量
2022-08-08 上传
664 浏览量
399 浏览量
2023-06-13 上传
191 浏览量
2024-09-26 上传
zk2008nick
- 粉丝: 2
- 资源: 3