最长递增子序列 LIS 时间复杂度O(nlogn)的Java实现
关于最长递增子序列时间复杂度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实现的更多相关文章
- 一个数组求其最长递增子序列(LIS)
一个数组求其最长递增子序列(LIS) 例如数组{3, 1, 4, 2, 3, 9, 4, 6}的LIS是{1, 2, 3, 4, 6},长度为5,假设数组长度为N,求数组的LIS的长度, 需要一个额外 ...
- 2.16 最长递增子序列 LIS
[本文链接] http://www.cnblogs.com/hellogiser/p/dp-of-LIS.html [分析] 思路一:设序列为A,对序列进行排序后得到B,那么A的最长递增子序列LIS就 ...
- 最长回文子序列LCS,最长递增子序列LIS及相互联系
最长公共子序列LCS Lintcode 77. 最长公共子序列 LCS问题是求两个字符串的最长公共子序列 \[ dp[i][j] = \left\{\begin{matrix} & max(d ...
- 动态规划(DP),最长递增子序列(LIS)
题目链接:http://poj.org/problem?id=2533 解题报告: 状态转移方程: dp[i]表示以a[i]为结尾的LIS长度 状态转移方程: dp[0]=1; dp[i]=max(d ...
- 最长递增子序列LIS再谈
DP模型: d(i) 以第 i 个元素结尾的最长递增子序列的长度. 那么就有 d(i) = max(d(j)) + 1;(j<i&&a[j]<a[i]),答案 max(d( ...
- 算法面试题 之 最长递增子序列 LIS
找出最长递增序列 O(NlogN)(不一定连续!) 参考 http://www.felix021.com/blog/read.php?1587%E5%8F%AF%E6%98%AF%E8%BF%9E%E ...
- 算法之动态规划(最长递增子序列——LIS)
最长递增子序列是动态规划中最经典的问题之一,我们从讨论这个问题开始,循序渐进的了解动态规划的相关知识要点. 在一个已知的序列 {a1, a 2,...an}中,取出若干数组成新的序列{ai1, ai ...
- 动态规划 - 最长递增子序列(LIS)
最长递增子序列是动态规划中经典的问题,详细如下: 在一个已知的序列{a1,a2,...,an}中,取出若干数组组成新的序列{ai1,ai2,...,aim},其中下标i1,i2,...,im保持递增, ...
- POJ 1836 Alignment 最长递增子序列(LIS)的变形
大致题意:给出一队士兵的身高,一开始不是按身高排序的.要求最少的人出列,使原序列的士兵的身高先递增后递减. 求递增和递减不难想到递增子序列,要求最少的人出列,也就是原队列的人要最多. 1 2 3 4 ...
随机推荐
- 把Android原生的View渲染到OpenGL Texture
http://blog.csdn.net/u010949962/article/details/41865777 最近要把Android 原生的View渲染到OpenGL GLSurfaceView中 ...
- 在unity 中,使用http请求,下载文件到可读可写路径
在这里我用了一个线程池,线程池参数接收一个带有object参数的,无返回值的委托 ,下载用到的核心代码,网上拷贝的,他的核心就是发起一个web请求,然后得到请求的响应,读取响应的流 剩下的都是常见的I ...
- MIPI DSI协议学习【转】
本文转载自:http://www.voidcn.com/blog/LoongEmbedded/article/p-6109759.html 1. MIPI DSI DSI:displayser ...
- UOJ132 【NOI2015】小园丁与老司机
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
- UOJ12 猜数
这一天,小Y.小D.小C正在愉快地玩耍. 小Y是个数学家,他一拍脑袋冒出了一个神奇的完全平方数 nn. 小D是个机灵鬼,很快从小Y嘴里套出了 nn 的值.然后在脑内把 nn 写成了 a×ba×b的形式 ...
- springboot项目支持war部署tomcat
最近在学校spring boot 在网络上学校到简单的启动spring boot项目,也搭建好了,但时实际情况我的spring boot项目是要发布到tomcat中的,今天,随意打了个war包发布到t ...
- IPC 进程间通信
linux下进程间通信的几种主要手段简介: 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它 ...
- wpf 界面平级之间设置上下顺序关系(ZIndex)
只能用于平级之间设置上下顺序 this.grid1.SetValue(Grid.ZIndexProperty, 9999); Panel.SetZIndex(th ...
- 13-THREE.JS 点光源
<!DOCTYPE html> <html> <head> <title>Example 03.02 - point Light</title&g ...
- 第六次scrum meeting记录
文章负责:刘斯盾 日期:2017年10月30日 会议地点:新主楼F座二楼 各组员工作情况 团队成员 昨日完成任务 明日要完成任务 赵晓宇 评分界面搭建 issue17 课程列表页面搭建 issue20 ...