关于最长递增子序列时间复杂度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)

import java.util.Arrays;
import java.util.Random; public class LISUpdate { public static void main(String[] args){ System.out.println("Generating a random array...");
LISUpdate lisUpdate=new LISUpdate();
int[] oldArray=new int[10];
oldArray=lisUpdate.randomArray();
System.out.println(Arrays.toString(oldArray)); //输出生成的随机数组
System.out.println("each LIS array:"); //输出每次计算时arrayOut数组的内容,便于观察
System.out.println("LIS length nlogn is:"+lisUpdate.getLength(oldArray)); //输出最长递增子序列的长度
} public int[] randomArray(){ //生成一个10以内的数组,长度为10
Random random=new Random();
int[] randomArray=new int[10];
for (int i = 0; i < 10; i++) {
randomArray[i]=random.nextInt(10);
} return randomArray;
} public int BinarySearchPosition(int arrayOut[],int left,int right,int key){ //二分查找要替换的位置 int mid; if (arrayOut[right]<key) {
return right+1;
}else {
while(left<right){
mid=(left+right)/2;
if (arrayOut[mid]<key) {
left=mid+1;
}else {
right=mid;
}
}
return left;
} } public int getLength(int[] arrayIn){ //获取最长递增子序列的长度 int position;
int len=1; int[] arrayOut=new int[arrayIn.length+1];//arrayOut[0]没有存放数据
arrayOut[1]=arrayIn[0]; //初始化,长度为1的LIS末尾为arrayIn[0]
for (int i = 1; i < arrayIn.length; i++) {
position=BinarySearchPosition(arrayOut, 1, len, arrayIn[i]);
arrayOut[position]=arrayIn[i];
System.out.println(Arrays.toString(arrayOut));
if (len<position) {
len=position;
}
} return len;
}

需要注意的是:上面代码中输出的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. 使用Java实现八种基本排序

    插入排序.选择排序.冒泡排序.希尔排序.堆排序.快速排序.归并排序.基数排序 import java.util.ArrayList; import java.util.List; /** * 排序算法 ...

  2. 20145231 《Java程序设计》第一周学习总结

    20145231 <Java程序设计>第一周学习总结 教材学习内容总结 Java三大平台Java SE,Java EE,Java ME.其中,Java SE是我们学习的基础. Java S ...

  3. mongodb的原子性(Atomicity)和事物 (Transactions)

    在mongodb中,单个的写操作保持原子性是在单个的document 上. $isolated operator $isolated 一个写操作多个documents 的时候可以防止和其他进程交织,一 ...

  4. codeforces 435B

    题意:只能对相邻的两个数字进行交换,允许k次交换,输出交换能得到的最大的数.从最高位开始寻找最优,每次寻找能交换的步数里交换到的最大值进行交换. #include<cstdio> #inc ...

  5. 分析新建的android代码

    1).xml文件中的<?xml version="1.0" encoding="utf-8"?>是每个xml文件开仅有一个的声明xml的代码. 2) ...

  6. 【转】服务器.htaccess 详解以及 .htaccess 参数说明

    htaccess文件(或者”分布式配置文件”)提供了针对目录改变配置的方法, 即,在一个特定的文档目录中放置一个包含一个或多个指令的文件, 以作用于此目录及其所有子目录.作为用户,所能使用的命令受到限 ...

  7. PAT1024. Palindromic Number (25)

    输入即为回文的情况要考虑 #include <iostream> #include <algorithm> //reverse using namespace std; str ...

  8. Flume-NG启动过程源码分析(三)(原创)

    上一篇文章分析了Flume如何加载配置文件的,动态加载也只是重复运行getConfiguration(). 本篇分析加载配置文件后各个组件是如何运行的? 加载完配置文件订阅者Application类会 ...

  9. JProgressBar与Timer的配套使用

    JProgressBar  的关键在于 setMaxium(int maxValue) 和 setValue(int progressValue); 当ProgressBar的当前值需要Control ...

  10. ​二十种实战调优MySQL性能优化的经验

    ​http://www.searchdatabase.com.cn/showcontent_58391.htm   [为查询缓存优化你的查询] 像 NOW() 和 RAND() 或是其它的诸如此类的S ...