单调递增最长子序列

博客探讨了如何找到一个序列中单调递增的最长子序列,内容涉及算法实现和优化。

单调递增最长子序列

时间限制: 3000 ms  |  内存限制: 65535 KB
难度: 4
最长单调递增子序列长度问题属于经典的动态规划问题,是约束条件下求大子集的问题,约束条件为子序列需严格按照递增条件产生,在此前提下求最长子序列,这类问题的衍生问题有很多,本质都是穷举大化子集 [^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]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值