最长上升子序列
来源:互联网 发布:欧特克软件价格 编辑:程序博客网 时间:2024/05/29 16:58
1.题目描述
传送门
2.code(java1.7版本)
n方的代码
import java.util.*;public class Main{ public static int N; public static void main(String[]args){ Scanner sc=new Scanner(System.in); while(sc.hasNext()){ N=sc.nextInt(); int[] ans=new int[N]; for(int i=0;i<N;i++){ ans[i]=sc.nextInt(); } System.out.println(help(ans)); } } public static int help(int[] ans){ int[] dp=new int[N]; dp[0]=1; for(int i=1;i<N;i++){ dp[i]=1; for(int j=0;j<i;j++){ if(ans[j]<ans[i])dp[i]=Math.max(dp[i],dp[j]+1); } } int max=0; for(int i=0;i<N;i++){ max=Math.max(max,dp[i]); } return max; }}
nlogn的代码
import java.util.*;public class Main{ static int[] ans=new int[10002]; static int[] dp=new int[10002]; static int len=0; static int N; public static void main(String[]args){ Scanner sc=new Scanner(System.in); while(sc.hasNext()){ N=sc.nextInt(); for(int i=0;i<N;i++){ ans[i]=sc.nextInt(); } dp[0]=ans[0]; len=1; for(int i=1;i<N;i++){ if(ans[i]>dp[len-1]){ dp[len++]=ans[i]; } else{ int pos=LIS(i); dp[pos]=ans[i]; } } System.out.println(len); } } public static int LIS(int i){ int left,right,mid; left=0; right=len-1; while(left<right){ mid=left+(right-left)/2; if(dp[mid]>=ans[i])right=mid; else{ left=mid+1; } } return left; }}
3.解题思路
运用一个辅助的数组dp来保存原数组以每个数结尾最长的子序列长度,假设存在一个序列a[1..9] = 2 1 5 3 6 4 8 9 7,我们可以很轻松的看出来它的LIS长度为5。但是如果一个序列太长后,就不能直接看出来了!
对于n方代码的思路
我们定义一个序列dp,它的长度和原数组的长度是一样长的,然后令 i = 1 to 9 逐个考察这个序列。首先,直接赋予dp[0]=1,因为第一个数结尾它的最长子序列一定为1。接着判断第2到第9个数,用i表示2-9,j表示0-i-1,如果a[j]小与a[i],这个时候需要更新dp[i]的值,将它赋予为max(dp[i],dp[j]+1),取最大的一个。这样循环完毕之后,dp数组保存的便是原数组中结尾的对应的最长子序列的长度,遍历一遍即可找出总的最长子序列长度。
对于nlogn代码的思路
对于n方复杂度的代码就是不断的对应更新dp数组的值,最后取出dp中最大的那个值即可;而对于nlogn的代码,更新dp的规则有一些变化,dp数组不一一对应保存原数组中每个结尾的最长子序列长度,描述它的更新规则,我们以下面的实例来看:
原数组为a[1..9] = 2 1 5 3 6 4 8 9 7,定义一个记录长度的变量len,下面开始填充dp数组。
第一步:直接赋值dp[0]=a[0],len为1,因为这个时候第一个元素,以它结尾的子序列长度肯定为1。这时的状态为dp 2,len=1.
第二步:考察a[1]这个数,这个时候直接看dp数组里面是有序的,先比较a[1]和dp[len-1]大小,这时a[1]比较小,则利用二分查找的方法,在dp数组里面查找刚好比a[1]大一步的数的下标,为0,这时直接将dp[0]更新为a[1].这时的状态dp 1,len 1.
第三步:考察a[2]这个数,还是比较a[2]和dp[len-1]大小,这时a[2]比较大,这直接赋值dp[1]为a[2],len加1.这时的状态,dp 1 5,len 2.
数据太多,偷个懒。。。
第四步到第九步,更新dp的规则还是按照第二步和第三步一样,最后的状态为dp 1 3 4 8,len 4.
最后整个序列的子序列长度即为len的大小。
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- jquer 的简输出
- SpringMVC的静态资源过滤设置/处理器设置
- C 内存管理
- Ubuntu上由于/boot容量不足无法更新系统
- 170821 制作UEFI模式Ubuntu启动U盘
- 最长上升子序列
- C#winform只能输入数字后不能复制粘贴问题
- VS一些常见问题处理(收集ing)
- csu1113模拟,STL
- java里绝对路径和相对路径的区别
- sequence list 线性表
- C语言结构体位段特性实现断言宏
- lower_bound以及upper_bound
- C 复习第一课 各个基础类型保存 以及表达式中一些表达方式