最长递增子序列粗解
带来了两个比较经典的求解最长递增子序列的题目
①点击打开链接 51nod 1134
基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题
给出长度为N的数组,找出这个数组的最长递增子序列。(递增子序列是指,子序列的元素是递增的)
例如:5 1 6 8 2 4 5 10,最长递增子序列是1 2 4 5 10。
Input
第1行:1个数N,N为序列的长度(2 <= N <= 50000)
第2 - N + 1行:每行1个数,对应序列的元素(-10^9 <= S[i] <= 10^9)
Output
输出最长递增子序列的长度。
Input示例
8
5
1
6
8
2
4
5
10
Output示例
5
最近在看动态规划 求解最长递增子序列有两种方法 一种是O(n^2) 一种是O(n^log(n))
对于这个题目只能用后者否则后几个例子会超时,但是这种办法只能求长度,求出来的顺序是不对的,贴上代码解释下。
#include<stdio.h>
#include<iostream>
#include <algorithm>
#include<string.h>
#include<math.h>
#include<queue>
#include<set>
#define LL long long
#define s(n) scanf("%d",&n)
#define p(n) printf("%d",n)
using namespace std;
int N[50050];
int dp[50050];
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
scanf("%d",&N[i]);
int top=1;
dp[1]=N[1];
for(int i=2;i<=n;i++)
{
if(N[i]<dp[1])//找到一个最小的数字
dp[1]=N[i];
else if(N[i]>dp[top])//找到当前一个最大的数
dp[++top]=N[i];
else//介于最小和最大之间的数字
{
int b=1,e=top;
while(b<e)
{
int mid=(b+e)/2;
if(dp[mid]<=N[i])//如果中间值比那个值小的话
{
b=mid+1;
}
else
e=mid;
}
dp[b]=N[i];
}
}
printf("%d\n",top);
}
return 0;
}
本方法就是不断更新对应位置的数字,比如 1 7 8 4 5 6
刚开始dp[1]=1 dp[2]=7 dp[3]=8 到了4的时候通过二分法找到了dp[2]>4 所以dp[2]=4,dp[3]=5,dp[4]=6; 通过这样的方式来更新,达到了二分 降低了复杂度。
②点击打开链接 POj2533
Longest Ordered Subsequence
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 54723 | Accepted: 24522 |
Description
A numeric sequence of
ai is ordered if
a1 <
a2 < ... <
aN. Let the subsequence of the given numeric sequence (
a1,
a2, ...,
aN) be any sequence (
ai1,
ai2, ...,
aiK), where 1 <=
i1 <
i2 < ... <
iK <=
N. For example, sequence (1, 7, 3, 5, 9, 4, 8) has ordered subsequences, e. g., (1, 7), (3, 4, 8) and many others. All longest ordered subsequences are of length 4, e. g., (1, 3, 5, 8).
Your program, when given the numeric sequence, must find the length of its longest ordered subsequence.
Your program, when given the numeric sequence, must find the length of its longest ordered subsequence.
Input
The first line of input file contains the length of sequence N. The second line contains the elements of sequence - N integers in the range from 0 to 10000 each, separated by spaces. 1 <= N <= 1000
Output
Output file must contain a single integer - the length of the longest ordered subsequence of the given sequence.
Sample Input
7 1 7 3 5 9 4 8
Sample Output
4也是求最长递增序列,没啥解释的,直接贴代码。
#include<stdio.h>
#include<iostream>
#include <algorithm>
#include<string.h>
#include<math.h>
#include<queue>
#include<set>
#define LL long long
#define s(n) scanf("%d",&n)
#define p(n) printf("%d",n)
using namespace std;
int N[1050];
int dp[1050];
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
memset(dp,0,sizeof(dp));
for(int i=0;i<n;i++)
scanf("%d",&N[i]);
int maxx=1;
dp[0]=1;
for(int i=1;i<n;i++)
{
dp[i]=1;
for(int j=0;j<i;j++)
{
if(N[j]<N[i] && dp[j]+1>dp[i])
{
dp[i]=dp[j]+1;
maxx=max(maxx,dp[i]);
}
}
}
printf("%d\n",maxx);
}
return 0;
}
二层for循环 查找更新