LIS
(最长上升子序列(计算机科学))
语音
编辑
锁定
讨论
上传视频
本词条缺少信息栏、概述图,补充相关内容使词条更完整,还能快速升级,赶紧来编辑吧!
最长上升子序列(Longest Increasing Subsequence,LIS),在计算机科学上是指一个序列中最长的单调递增的子序列。
目录
LIS实现
编辑
语音
有两种,时间复杂度分别为O(n^2)与O(n log n),空间复杂度均为O(n)。
O(n^2)的方法:
#include
#include
#include
#include
#include
#include
using namespace std;
stack index;
int a[15010], dp[15010], front[15010];//front记结点前驱
int n;
inline void ir() {
cin >> n;
return;
}
int main() {
ir();
int maxn = 0;
for (int i = 1; i <= n; i++)
{
scanf_s("%d", &a[i]);
dp[i] = 1;
front[i] = -1; //初始化
for (int j = 1; j
if (a[j]
{
if (dp[j] + 1 > dp[i])
{
dp[i] = dp[j] + 1;
front[i] = j;
}
}
maxn = max(maxn, dp[i]);
}
cout <
int k = 0;
for (int i = 1; i <= n; i++)
if (dp[i] == maxn)
k = i;
while (k != -1)
{
index.push(k);
k = front[k];
}
while (!index.empty()) {
cout <
index.pop();
}
return 0;
}
O(n log n)的方法:
#include
#include
using namespace std;
int n,a[20010];
int c[20010];
int len=0;
int find(int x)
{
int l=1,r=len,mid;
while(l<=r)
{
mid=(l+r)>>1;
if(x>c[mid])l=mid+1;
//记忆方法:求上升序列,就表示x更大,那么就是大于
else
r=mid-1;
}
return l;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
{
int k=find(a[i]);
c[k]=a[i];
len=max(len,k);
}
printf("%d",len);
return 0;
}
LIS应用
编辑
语音
LIS经常用于确定一个代价最小的调整方案,使一个序列变为升序。只需要固定LIS中的元素,调整其他元素即可。