LIS(两种方法求最长上升子序列)
2024-10-01 01:06:38
首先得明白一个概念:子序列不一定是连续的,可以是断开的。
有两种写法:
一、动态规划写法
复杂度:O(n^2)
代码:
#include <iostream>
#include <queue>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#define INF 0x3f3f3f3f using namespace std;
typedef long long ll;
const int maxn = ;
int a[maxn],dp[maxn]; int main()
{
ios::sync_with_stdio(false);
int n;
while(cin>>n && n)
{
for(int i = ; i<n; i++)
cin>>a[i];
int mmax = -;
for(int i = ; i<n; i++)
{
dp[i] = ;
for(int j = ; j<i; j++)//遍历之前的每一个元素pre
{
if(a[j]<a[i] && (dp[j]+>dp[i]))//如果元素pre < 当前元素cur,而且pre的长度+1要比当前的长度多就更新当前的长度
{
dp[i] = dp[j]+;
}
}
mmax = max(mmax,dp[i]);//维护最大的长度
}
printf("%d\n",mmax);
}
return ;
}
二、low_bound写法
复杂度:O(nlogn)
这种写法就是将动规写法中的第二层的遍历改为了二分查找。所以复杂度变为O(nlogn)
该算法中开了一个辅助数组h来表示该长度下最后的元素的最小值。例如 1、2、0、5 、-1
为什么要修改h数组里边的数为小的值呢,因为修改后h数组能变长的潜力就增大了,所以要修改。
代码:
#include <iostream>
#include <queue>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#define INF 0x3f3f3f3f using namespace std;
typedef long long ll;
const int maxn = ;
int a[maxn],dp[maxn]; int main()
{
ios::sync_with_stdio(false);
int n;
while(cin>>n)
{
memset(a,,sizeof(a));
for(int i = ; i<n; i++)
dp[i] = INF;
for(int i = ; i<n; i++)
cin>>a[i];
int mmax = -;
for(int i = ; i<n; i++)
{
int k = lower_bound(dp, dp+n, a[i])-dp;
dp[k] = a[i];
mmax = max(mmax, k+);
}
printf("%d\n",mmax);
}
return ;
}
最新文章
- P3381 【模板】最小费用最大流
- error C2504 类的多层继承 头文件包含
- SC.UI
- 40. Interleaving String
- 在CentOS安装cobbler自动化部署软件
- Android各个文件夹对应的分辨率?
- 【poj2891-Strange Way to Express Integers】拓展欧几里得-同余方程组
- [GeekBand]C++高级编程技术(2)
- iOS开发——点击图片全屏显示
- sqlserver自定义函数
- 天上掉Pizza
- struts标签怎么判断request里的属性是否为空 <;s:if test=";${list==null}";>; <;/s:if>;
- LeetCode算法题-Third Maximum Number(Java实现-四种解法)
- queryset优化 。。。。。exists()与iterator()方法
- BDD 与DSL 入门
- .NET创建一个即是可执行程序又是Windows服务的程序
- 获取【酷我音乐】歌曲URL地址
- error:No buffer space available (maximum connections reached
- PHP在 win7 64位 旗舰版 报错 Call to undefined function curl_init()
- 汇编_指令_LEA和MOV的区别