打卡Day 8:最长递增子序列

原题链接http://bailian.openjudge.cn/practice/2757

描述

一个数的序列bi,当b1 < b2 < ... < bS的时候,我们称这个序列是上升的。对于给定的一个序列(a1a2, ..., aN),我们可以得到一些上升的子序列(ai1ai2, ..., aiK),这里1 <= i1 < i2 < ... < iK <= N。比如,对于序列(1, 7, 3, 5, 9, 4, 8),有它的一些上升子序列,如(1, 7), (3, 4, 8)等等。这些子序列中最长的长度是4,比如子序列(1, 3, 5, 8).

你的任务,就是对于给定的序列,求出最长上升子序列的长度。

输入

输入的第一行是序列的长度N (1 <= N <= 1000)。第二行给出序列中的N个整数,这些整数的取值范围都在0到10000。

输出

最长上升子序列的长度。

样例输入

7
1 7 3 5 9 4 8

样例输出

4

动态规划,设一个数num在数组中的位置是i,那么只要遍历数组0-i并找出最长递增子序列即可,如果在其中找到一个a[j]<a[i],则动态规划,dp方程为maxn=max(a[i],a[j]+1);

显然他的时间复杂度为On方

代码如下:

#include<iostream>
#include<algorithm>
using namespace std;
int a[1010],n,ans[1010];
//优化??? 
int main()
{
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>a[i];
	}
	for(int i=0;i<n;i++){
		for(int j=0;j<i;j++){
		if(a[i]>a[j]){
			ans[i]=max(ans[j]+1,ans[i]);
		}	
		}
	}
	int maxn=0;
	for(int i=0;i<n;i++){
		if(ans[i]>maxn){
			maxn=ans[i];
		}
	}
	cout<<maxn+1;//ans数组初始值为0,但只有一个数的时候ans应该为1,所以最后结果应该加上自己 
	return 0;
}

On方还是有点高了,怎么优化呢,很显然这只能从内层循环从0到i遍历入手,要是这个数组是个有序的就能用二分来降低时间复杂度到O(nlogn)了。

哥们虽然想到了这层但想了很久也不知道怎么有序而又不影响别的(铸币是这样的),然后看了题解悟了,题解是这篇 

https://leetcode.cn/problems/longest-increasing-subsequence/solution/zui-chang-shang-sheng-zi-​​​​​​xu-lie-dong-tai-gui-hua-2/​​​​​​​s​​​​​​​s

新建了一个tail数组,tail[i]表示i+1长的子序列的最小结尾元素,可以保证一定是有序的,原题解证明了我就不再这多说,然后只要遍历输入数组不断更新tail元素即可。答案就是tails数组的长度。

代码如下

#include<iostream>
using namespace std;
int a[1010],tail[1010]; 
int n;
int erfendp(){
	int ans=0;
	for(int i=0;i<n;i++){
		int l=0,r=ans;
		while(l<r){//找到a[i]在tail中的位置 
			int m=l+(r-l)/2;
			if(tail[m]<a[i]){ 
				l=m+1;
			}
			else{
				r=m;
			}
		}
		tail[l]=a[i];
		if(ans==r){
			ans++;
		}
	}
	return ans;
}
int main()
{
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>a[i];
	}
	cout<<erfendp();
	return 0;
 } 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值