关于最长递增子序列时间复杂度O(n^2)的实现方法在博客http://blog.csdn.net/iniegang/article/details/47379873(最长递增子序列 Java实现)中已经做了实现,但是这种方法时间复杂度太高,查阅相关资料后我发现有人提出的算法可以将时间复杂度降低为O(nlogn),这种算法的核心思想就是替换(二分法替换),以下为我对这中算法的理解: 
假设随机生成的一个具有10个元素的数组arrayIn[1-10]如[2, 3, 3, 4, 7, 3, 1, 6, 6, 4],求这个数组的最长递增子序列。 
首先定义一个数组arrayOut[1-10]来逐个寻找arrayIn[1-10]中以第i个元素结尾的最长递增子序列的长度。 
定义len来计算相应的长度 
(1)将arrayIn[1]放入arrayOut,此时arrayOut[1]=arrayIn[1]=2,此时len=1; 
(2)将arrayIn[2]放入arrayOut,此时要先寻找arrayIn[2]应该放入的位置,由于arrayIn[2]=3>arrayOut[1]=2,那么arrayIn[2]应该放入的位置为arrayOut[2],这时arrayOut[2]=arrayIn[2]=3,此时len=2; 
(3)将arrayIn[3]放入arrayOut,此时要先寻找arrayIn[3]应该放入的位置,由于arrayIn[3]=3=arrayOut[2]=3,那么arrayIn[3]应该放入的位置为arrayOut[2],这时arrayOut[2]=arrayIn[3]=3,即此时进来的arrayIn[3]替换掉了arrayOut[2],此时len仍然为2; 
(4)对数组arrayIn的后续元素执行以上类似的操作即 
如果arrayIn要放入的元素比arrayOut最后一个元素大的话就放在其后; 
否则寻找一个替换的位置 
这样以来arrayIn元素放入的位置即为len的值,然后判断这次得到的len值与上次的len值的大小,向大的方向更新即可。 
使用二分法来查找arrayIn元素应该放入的位置即可将时间复杂度降为O(nlogn)。 
以下为具体的实现代码(java)

  1. import java.util.Arrays;
  2. import java.util.Random;
  3. public class LISUpdate {
  4. public static void main(String[] args){
  5. System.out.println("Generating a random array...");
  6. LISUpdate lisUpdate=new LISUpdate();
  7. int[] oldArray=new int[10];
  8. oldArray=lisUpdate.randomArray();
  9. System.out.println(Arrays.toString(oldArray)); //输出生成的随机数组
  10. System.out.println("each LIS array:"); //输出每次计算时arrayOut数组的内容,便于观察
  11. System.out.println("LIS length nlogn is:"+lisUpdate.getLength(oldArray)); //输出最长递增子序列的长度
  12. }
  13. public int[] randomArray(){ //生成一个10以内的数组,长度为10
  14. Random random=new Random();
  15. int[] randomArray=new int[10];
  16. for (int i = 0; i < 10; i++) {
  17. randomArray[i]=random.nextInt(10);
  18. }
  19. return randomArray;
  20. }
  21. public int BinarySearchPosition(int arrayOut[],int left,int right,int key){ //二分查找要替换的位置
  22. int mid;
  23. if (arrayOut[right]<key) {
  24. return right+1;
  25. }else {
  26. while(left<right){
  27. mid=(left+right)/2;
  28. if (arrayOut[mid]<key) {
  29. left=mid+1;
  30. }else {
  31. right=mid;
  32. }
  33. }
  34. return left;
  35. }
  36. }
  37. public int getLength(int[] arrayIn){ //获取最长递增子序列的长度
  38. int position;
  39. int len=1;
  40. int[] arrayOut=new int[arrayIn.length+1];//arrayOut[0]没有存放数据
  41. arrayOut[1]=arrayIn[0]; //初始化,长度为1的LIS末尾为arrayIn[0]
  42. for (int i = 1; i < arrayIn.length; i++) {
  43. position=BinarySearchPosition(arrayOut, 1, len, arrayIn[i]);
  44. arrayOut[position]=arrayIn[i];
  45. System.out.println(Arrays.toString(arrayOut));
  46. if (len<position) {
  47. len=position;
  48. }
  49. }
  50. return len;
  51. }

需要注意的是:上面代码中输出的arrayOut数组并不是最长递增子序列,我这里选择将其输出只是为了验证算法的执行过程。

对于求最长递减子序列,则可以直接将原数组进行“反转”操作,然后求出反转之后的数组的最长递增子序列的长度即为最长递减子序列的长度。

最长递增子序列 LIS 时间复杂度O(nlogn)的Java实现的更多相关文章

  1. 一个数组求其最长递增子序列(LIS)

    一个数组求其最长递增子序列(LIS) 例如数组{3, 1, 4, 2, 3, 9, 4, 6}的LIS是{1, 2, 3, 4, 6},长度为5,假设数组长度为N,求数组的LIS的长度, 需要一个额外 ...

  2. 2.16 最长递增子序列 LIS

    [本文链接] http://www.cnblogs.com/hellogiser/p/dp-of-LIS.html [分析] 思路一:设序列为A,对序列进行排序后得到B,那么A的最长递增子序列LIS就 ...

  3. 最长回文子序列LCS,最长递增子序列LIS及相互联系

    最长公共子序列LCS Lintcode 77. 最长公共子序列 LCS问题是求两个字符串的最长公共子序列 \[ dp[i][j] = \left\{\begin{matrix} & max(d ...

  4. 动态规划(DP),最长递增子序列(LIS)

    题目链接:http://poj.org/problem?id=2533 解题报告: 状态转移方程: dp[i]表示以a[i]为结尾的LIS长度 状态转移方程: dp[0]=1; dp[i]=max(d ...

  5. 最长递增子序列LIS再谈

    DP模型: d(i) 以第 i 个元素结尾的最长递增子序列的长度. 那么就有 d(i) = max(d(j)) + 1;(j<i&&a[j]<a[i]),答案 max(d( ...

  6. 算法面试题 之 最长递增子序列 LIS

    找出最长递增序列 O(NlogN)(不一定连续!) 参考 http://www.felix021.com/blog/read.php?1587%E5%8F%AF%E6%98%AF%E8%BF%9E%E ...

  7. 算法之动态规划(最长递增子序列——LIS)

    最长递增子序列是动态规划中最经典的问题之一,我们从讨论这个问题开始,循序渐进的了解动态规划的相关知识要点. 在一个已知的序列 {a1, a 2,...an}中,取出若干数组成新的序列{ai1, ai ...

  8. 动态规划 - 最长递增子序列(LIS)

    最长递增子序列是动态规划中经典的问题,详细如下: 在一个已知的序列{a1,a2,...,an}中,取出若干数组组成新的序列{ai1,ai2,...,aim},其中下标i1,i2,...,im保持递增, ...

  9. POJ 1836 Alignment 最长递增子序列(LIS)的变形

    大致题意:给出一队士兵的身高,一开始不是按身高排序的.要求最少的人出列,使原序列的士兵的身高先递增后递减. 求递增和递减不难想到递增子序列,要求最少的人出列,也就是原队列的人要最多. 1 2 3 4 ...

随机推荐

  1. 九、goroutine和channel

    进程和线程 A)进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单元 B)线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位 C)一个进 ...

  2. Linux下的文件查找命令——find

    Linux下几个常见的文件查找命令: which       查看可执行文件的位置 whereis    寻找特定文件,查看文件的位置 locate       配合数据库查看文件位置 find    ...

  3. gitblit搭建git服务器

    如果你的公司使用git作为版本管理工具,那么对gitblit应该也不会陌生.gitblit是一个开源的git服务器java实现,一般情况下gitblit都是由别人已经搭建好你直接使用就行了,除非你就是 ...

  4. Netsh 命令详解

    1. help帮助指南 2. 常用命令介绍netsh interface ip show addressnetsh interface ip dumpnetsh interface ip dump & ...

  5. 生产环境中,通过域名映射ip切换工具SwitchHosts

    项目中,经常需要配置host.将某个域名指向某个ip.手动配置C:\Windows\System32\drivers\etc\hosts,非常不方便.这里分享一个可以高效切换host工具:Switch ...

  6. streambase service 变为 window service启动

    1.配置出.sbdeploy文件 2.安装streambase服务 streambase command line :--install-service 即可安装对应的的window service ...

  7. RGB(16进制)_转_TColor

    ZC:内存中 COLORREF就是一个DWORD(从定义"COLORREF = DWORD;"就可以看出来),但是 具体的byte R/G/B 的位置是怎么方式的? ZC:Wind ...

  8. review18

    数字格式化 程序可以直接使用String类调用format方法对数字进行格式化. format方法中的“格式化模式”是一个用双引号括起的字符序列(字符串),该字符序列的字符由格式符和普通字符所构成.代 ...

  9. UML类图(二)----------类与类之间的关系之关联(聚合与组合)

    类与类之间的关系: 在软件系统中,类并不是孤立存在的,类与类之间存在各种关系,对于不同类型的关系,UML提供了不同的表示方式.       1. 关联关系 关联(Association)关系是类与类之 ...

  10. VMware设置NAT网络及 CentOS 7IP配置

    1.打开VMware,选择  编辑, 虚拟网络编辑器 2.默认情况下,VMware8为我们NAT所使用的网卡,选中VMnet8 3.此处设置我们的IP地址,这个随便指定,我这里设置成192.168.2 ...