本文的讲解摘自《挑战程序设计竞赛》
不过说实话最长上升子序列这个概念并不难,我觉得难的是你能够把题目中的意思和解法抽象成最长上升子序列
废话不多说了开始讲解第一种算法
定义dp[i] 表示以ai结尾的最长上升子序列的长度
这时呢又分为两种情况
第一只包含ai
第二 前面的长度 + ai
所以得到递推式
dp[i] = max(1,dp[j] + 1);
代码如下:
void solve()
{
int res = 0;
int i,j;
for( i = 0;i < n;i++)
{
dp[i] = 1; //最长上升子序列只有他自己,所以长度为1
for(j = 0;j < i;j++)
{
if(a[j] < a[i]) //只有j下标的a小于i下标的a 才能构成上升子序列
dp[i] = max(dp[i],dp[j] + 1); //从0开始到当前的i中
}
res = max(res,dp[i]); //挑选最大的上升子序列
}
cout<<res<<endl;
}
这种算法的复杂度是o(n^2) 太大了 一般不能满足题目的解题需求
所以再给出 o(nlog(n))复杂度的算法
当长度相同时每次都找最小的值放在最后因为这样在以后的查找中更有优势
代码如下 这时利用了 STL中的一个函数
void solve()
{
int i,j;
int dp[10000];
for(i = 0;i < n;i++)
dp[i] = INF;
for( i = 0;i < n;i++)
{
*lower_bound(dp,dp+n,a[i]) = a[i];
}
cout<<lower_bound(dp,dp+n,INF) - dp<<endl;
}
最后可以留一个简单的题目:
给定你一组任意的数字 这组数字使乱序的 比如 1,32,12,34,0,21,324,21,,,,
请你找出如何删除最少的数字让剩下的数字有序?
提升:应用最长上升子序列!