问题描述:给出一个序列a1,a2,a3,a4,a5,a6,a7....an,求它的一个子序列(设为s1,s2,...sn),使得这个子序列满足这样的性质,s1<s2<s3<...<sn并且这个子序列的长度最长。输出这个最长的长度。

O(n^2)算法:

我们依次遍历整个序列,每一次求出从第一个数到当前这个数的最长上升子序列,直至遍历到最后一个数字为止,然后再取dp数组里最大的那个即为整个序列的最长上升子序列。我们用dp[i]来存放序列1-i的最长上升子序列的长度,那么dp[i]=max(dp[j])+1,(j∈[1, i-1]); 显然dp[1]=1,我们从i=2开始遍历后面的元素即可。下面是模板:

int LIS(T a[],int n)
{int i,j;int ans=1;int m=0;int *dp=new int[n+1];dp[1]=1;for(i=2;i<=n;i++){m=0;for(j=1;j<i;j++){if(dp[j]>m&&a[j]<a[i])m=dp[j];}dp[i]=m+1;if(dp[i]>ans)ans=dp[i];}return ans;
}

O(nlogn)算法:

定义d[k]:长度为k的上升子序列的最末元素,若有多个长度为k的上升子序列,则记录最小的那个最末元素。
注意d中元素是单调递增的,下面要用到这个性质。
首先len = 1,d[1] = a[1],然后对a[i]:若a[i]>d[len],那么len++,d[len] = a[i];
否则,我们要从d[1]到d[len-1]中找到一个j,满足d[j-1]<a[i]<d[j],则根据D的定义,我们需要更新长度为j的上升子序列的最末元素(使之为最小的)即 d[j] = a[i];
最终答案就是len
利用d的单调性,在查找j的时候可以二分查找,从而时间复杂度为nlogn。

假设存在一个序列d[1..9] = 2 1 5 3 6 4 8 9 7,可以看出来它的LIS长度为5。n
下面一步一步试着找出它。
我们定义一个序列B,然后令 i = 1 to 9 逐个考察这个序列。
此外,我们用一个变量Len来记录现在最长算到多少了

首先,把d[1]有序地放到B里,令B[1] = 2,就是说当只有1一个数字2的时候,长度为1的LIS的最小末尾是2。这时Len=1

然后,把d[2]有序地放到B里,令B[1] = 1,就是说长度为1的LIS的最小末尾是1,d[1]=2已经没用了,很容易理解吧。这时Len=1

接着,d[3] = 5,d[3]>B[1],所以令B[1+1]=B[2]=d[3]=5,就是说长度为2的LIS的最小末尾是5,很容易理解吧。这时候B[1..2] = 1, 5,Len=2

再来,d[4] = 3,它正好加在1,5之间,放在1的位置显然不合适,因为1小于3,长度为1的LIS最小末尾应该是1,这样很容易推知,长度为2的LIS最小末尾是3,于是可以把5淘汰掉,这时候B[1..2] = 1, 3,Len = 2

继续,d[5] = 6,它在3后面,因为B[2] = 3, 而6在3后面,于是很容易可以推知B[3] = 6, 这时B[1..3] = 1, 3, 6,还是很容易理解吧? Len = 3 了噢。

第6个, d[6] = 4,你看它在3和6之间,于是我们就可以把6替换掉,得到B[3] = 4。B[1..3] = 1, 3, 4, Len继续等于3

第7个, d[7] = 8,它很大,比4大,嗯。于是B[4] = 8。Len变成4了

第8个, d[8] = 9,得到B[5] = 9,嗯。Len继续增大,到5了。

最后一个, d[9] = 7,它在B[3] = 4和B[4] = 8之间,所以我们知道,最新的B[4] =7,B[1..5] = 1, 3, 4, 7, 9,Len = 5。

于是我们知道了LIS的长度为5。

注意。这个1,3,4,7,9不是LIS(LIS为1,3,4,8,9),它只是存储的对应长度LIS的最小末尾。虽然最后一个d[9] = 7更新进去对于这组数据没有什么意义,但是如果后面再出现两个数字 8 和 9,那么就可以把8更新到d[5], 9更新到d[6],得出LIS的长度为6。

利用杭电ACM上的题目来检验自己的代码: http://acm.hdu.edu.cn/showproblem.php?pid=1950 该题的大意就是从426315(只看图的右边)这种序列中找到最长上升序列,由于不会出现13534这种种含有重复数字的,因此对二分部分就算有边界错误的情况也能AC,但是还是要注意我们要找的应该是第一个大于当前要插入的数的数。

import java.util.Scanner;public class Main {public static void main(String[] args) {int i,j,n,p,len,index;int[] dp = null,arr = null;Scanner sc=new Scanner(System.in);n=sc.nextInt();for(i=1;i<=n;i++){len=0;p=sc.nextInt();dp=new int[p+1];arr=new int[p+1];for(j=1;j<=p;j++){arr[j]=sc.nextInt();}dp[++len]=arr[1];for(j=2;j<=p;j++){if(arr[j]>dp[len]){dp[++len]=arr[j];}index=bsearch(dp,arr[j],1,len);dp[index]=arr[j];}System.out.println(len);}}private static int bsearch(int[] dp, int value,int start,int end) {int mid;while(start<end){mid=(start+end)/2;if(dp[mid]>value){end=mid;}else{start=mid+1;}}return start;}
}

Java实现O(nlogn)最长上升子序列相关推荐

  1. Java输出数组中最长递增子序列的代码

    下面内容是关于Java输出数组中最长递增子序列的内容,希望对大伙有较大用途. package com.wzs;import java.util.ArrayList; import java.util. ...

  2. c语言最长递增子序列nlogn,最长递增子序列

    问题定义: 给定一个长度为N的数组,找出一个最长的单调自增子序列(不一定连续,但是顺序不能乱).例如:给定一个长度为6的数组A{5, 6, 7, 1, 2, 8},则其最长的单调递增子序列为{5,6, ...

  3. java lcs_Java算法之最长公共子序列问题(LCS)实例分析

    本文实例讲述了Java算法之最长公共子序列问题(LCS).分享给大家供大家参考,具体如下: 问题描述:一个给定序列的子序列是在该序列中删去若干元素后得到的序列.确切地说,若给定序列X= { x1, x ...

  4. 【CodeForces - 340D】Bubble Sort Graph (思维,nlogn最长上升子序列类问题)

    题干: Iahub recently has learned Bubble Sort, an algorithm that is used to sort a permutation with n e ...

  5. 最长上升子序列(LIS) nlogn解法

    文章目录 经典DP解法O(n^2) dp+二分法(O(nlogn)) 最长上升子序列LIS:Longest increasing subsequence 题目链接:Leetcode300. 最长递增子 ...

  6. 动态规划示例汇总-Java版(组合硬币、跳台阶、最小路径和、最长递增子序列、最长公共子序列、01背包问题、最小编辑代价)

    动态规划算法示例汇总-Java版 组合硬币 Java解题-暴力搜索 Java解题-记忆搜索 Java解题-动态规划(两种写法) 跳台阶 Java解题-暴力递归 Java解题-动态规划 矩阵最小路径和 ...

  7. 模板 - 最长上升子序列与最长公共子序列

    整理的算法模板合集: ACM模板 目录 1.最长上升子序列(LIS) 1.1树状数组优化O(nlogn)O(nlogn)O(nlogn) 2.最长公共子序列(LCS) 2.1转换成LIS优化O(nlo ...

  8. 最长上升子序列 java_最长上升子序列 O(nlogn)解法 (java)

    最长递增子序列问题:在一列数中寻找一些数,这些数满足:任意两个数a[i]和a[j],若i 设dp[i]表示以i为结尾的最长递增子序列的长度,则状态转移方程为: dp[i] = max{dp[j]+1} ...

  9. c语言最长递增子序列nlogn,十月常见算法考题、最长递增子序列,Leetcode第300题最长上升子...

    十月常见算法考题.最长递增子序列,Leetcode第300题最长上升子 十月常见算法考题.最长递增子序列,Leetcode第300题最长上升子序列的变种,我没见过乔丹,今天詹姆斯就是我的神! @Aut ...

最新文章

  1. INS-20802 PRVF-9802 PRVF-5184 PRVF-5186 After Successful Upgradeto 11gR2 Grid Infrastructure
  2. python手机app 授权登录_Appium+unittest+python登录app
  3. Docker 运行的 应用程序无法连接Oracle数据库的解决办法
  4. Linux中的基础IO(二)
  5. 计算机程程序员英语,计算机程序员常用英语词汇(2)
  6. 海康+萤石云+云存储多少钱一个月_400万极清画质 萤石C6Wi智能家居摄像机
  7. python抽取指定url页面的title_Python新手写爬虫全过程记录分析
  8. 计算机使用快捷键大全
  9. 2022年华为杯中国研究生数学建模竞赛C题思路
  10. 反向传播算法(代码笔记)
  11. Linux切换jdk版本
  12. 99美金和299美金的开发者证书的区别
  13. qq计算机无法启动程序丢失MS,Win10无法运行QQ怎么回事 QQ提示缺少MSVCR100.dll解决方法...
  14. 为大地增添一抹绿色植树节公益活动
  15. Python移动自动化测试面试准备
  16. JVM-详解G1垃圾收集器
  17. .xin 是什么域名?个人能使用吗?
  18. 【数学建模】熵值法与多指标评价系统
  19. 你见过几次四大天王同台啊
  20. Spark 内存管理存储内存管理_尚硅谷大数据培训

热门文章

  1. be 动词 时态变化
  2. 百度AI评测:红酒识别
  3. 视觉SLAM十四讲CH3代码解析及课后习题详解
  4. 20年的分享页面signature
  5. 卡马克:用C++进行函数式编程
  6. 最详细的A/B test 原理
  7. Mac录屏,同时保留声音
  8. 惠普总裁关于职业规划的讲座
  9. Oracle报错:不是单组分组函数
  10. Ubuntu常用软件安装与问题解决(持续更新)