最长单调递增子序列长度问题属于经典的动态规划问题,是约束条件下求最大子集的问题,约束条件为子序列需严格按照递增条件产生,在此前提下求最长的子序列,这类问题的衍生问题有很多,本质都是穷举最大化子集 [^3]。
对于该问题,有不同的解决思路。一种常规方法如在代码示例中,通过两层循环来计算每个元素结尾的单调递增最长子序列长度。定义数组`a`存储输入序列,数组`b`存储以每个元素结尾的单调递增最长子序列长度,初始`b`数组元素值都为 1,因为一个元素自身的最长递增子序列长度为 1。通过两层循环,外层循环遍历数组元素,内层循环从`a[0]`到当前元素`a[i]`,若`a[i] > a[j]`且`b[j] > b[i] - 1`,则更新`b[i] = b[j] + 1`,最后找出`b`数组中的最大值即为最长单调递增子序列长度 [^4]。
代码示例如下:
```cpp
#include <iostream>
using namespace std;
int a[100001], b[100001];
int max(int n, int a[], int b[]) {
for(int i = 1; i < n; i++){
for(int j = 0; j < i; j++){
if(a[i] > a[j] && b[j] > b[i] - 1){
b[i] = b[j] + 1;
}
}
}
int m = b[0];
for(int i = 1; i < n; i++){
if(b[i] > m) m = b[i];
}
return m;
}
int main() {
int n;
cin >> n;
for(int i = 0; i < n; i++){
cin >> a[i];
b[i] = 1;
}
cout << max(n, a, b);
}
```
此外,还可以采用更好的方法。在计算过程中,计算`dp[i]`时,不必每次都寻找到`arr[i - 1]`为止的每个元素结尾的单调递增最长子序列的最大值,可排除一些不可能产生最优解的子序列。例如对于`arr[x]`和`arr[y]`,它们的单调递增最长子序列分别为 1,3,7 和 1,3,15,长度均为 3,若要在后面添加元素使其更长,在 1,3,7 后面添加元素得到的子序列可能更长,所以 1,3,15 这个序列在后续更新中无需考虑。只需保留每个长度的单调递增子序列的最后一个元素,然后进行更新,寻找可能的更大长度的递增子序列 [^1]。
例如对于数组`{3, 18, 7, 14, 10, 12, 23, 41, 16, 24}`,就是要找出一个最长的单调递增子序列(不一定连续,但顺序不能乱),像给定数组`A = {5, 6, 7, 1, 2, 8, 9}`,其最长的单调递增子序列为`{5, 6, 7, 8, 9}`,长度为 5 [^2]。