LIS的O(nLogN)算法
今天回顾WOJ1398,发现了这个当时没有理解透彻的算法。
看了好久好久,现在终于想明白了。
试着把它写下来,让自己更明白。
最长递增子序列,Longest Increasing Subsequence 下面我们简记为 LIS。
排序+LCS算法 以及 DP算法就忽略了,这两个太容易理解了。
假设存在一个序列d[1..9] = 2 1 5 3 6 4 8 9 7,可以看出来它的LIS长度为5。
下面一步一步试着找出它。
我们定义一个序列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的最小末尾。有了这个末尾,我们就可以一个一个地插入数据。虽然最后一个d[9] = 7更新进去对于这组数据没有什么意义,但是如果后面再出现两个数字 8 和 9,那么就可以把8更新到d[5], 9更新到d[6],得出LIS的长度为6。
然后应该发现一件事情了:在B中插入数据是有序的,而且是进行替换而不需要挪动——也就是说,我们可以使用二分查找,将每一个数字的插入时间优化到O(logN)~~~~~于是算法的时间复杂度就降低到了O(NlogN)~!
代码如下:
int LIS(int d[], int n){
int *B = new int[n];
int left, right, mid, len = 1;
B[0] = d[1]; //为了和上面的一致,我们从1开始计数吧:)
for(i = 2; i <= n; ++i){
left = 0, right = len;
while(left <= right){
mid = (left + right) / 2;
if(B[mid] < d[i]) left = mid + 1; //二分查找d[i]的插入位置
else right = mid - 1;
}
B[left] = d[i]; //插入
if(left > len) len++; //d[i]比现有的所有数字都大,所以left 才会大于 len。
}
delete[] B;
return len;
}
--
转载请注明出自 http://www.felix021.com/blog/read.php?1587 ,如是转载文则注明原出处,谢谢:)
LIS的O(nLogN)算法相关推荐
- 求最长上升子序列——LIS的O(nlogn)算法(二分)
LIS的O(nlogn)算法(二分) 传送门:点我 O(n^2)解法:(n为4w,TLE) memset(dp,1,sizeof(dp)); int ans=-1; for(i=2; i<=n; ...
- LIS的O(nlogn)算法(二分)
[hdu1950]Bridging signals 传送门:点我 =================================== O(n^2)解法:(n为4w,TLE) memset(dp,1 ...
- 【训练题】航线设计 | 使用最长上升子序列(LIS)长度的O(nlogn)算法优化
[问题描述] 有一个国家被一条河划分为南北两部分,在南岸和北岸总共有N对城镇,每一城镇在对岸都有唯一的友好城镇.任何两个城镇都没有相同的友好城镇.每一对友好城镇都希望有一条航线来往.于是他们向政府提出 ...
- 最长连续子序列nlogn算法
最长上升子序列(LIS)长度的O(nlogn)算法 标签: 算法search优化存储 2012-04-18 19:38 14031人阅读 评论(5) 收藏 举报 分类: 资料学习(15) 解题报告 ...
- 最长不下降子序列的O(n^2)算法和O(nlogn)算法
转帖 最长不下降子序列的O(n^2)算法和O(nlogn)算法 最长不下降子序列(LIS:Longest Increasing Subsequence) //用句通俗的话说,我讲的很通俗易懂~~ 问题 ...
- 最长递增子序列 O(NlogN)算法
最长递增子序列 O(NlogN)算法 今天回顾WOJ1398,发现了这个当时没有理解透彻的算法. 看了好久好久,现在终于想明白了. 试着把它写下来,让自己更明白. 最长递增子序列,Longest In ...
- 浅析拯救小矮人的 nlogn 算法及其证明
浅析拯救小矮人的 nlogn 算法及其证明 题型简介: 有 $ n $ 个人,第 $ i $ 个人身高 $ a_i $ 手长 $ b_i $ ,他们为了从一个高为 $ H $ 的洞中出去,决定搭人梯. ...
- 最长上升子序列(O(nlogn))算法并输出最长上升子序列
最长上升子序列普通算法 dp[n]表示以a[n]结尾的最长上升子序列长度 显然有 dp[n]=max(dp[n],dp[i]+1) 满足a[i]<a[n],1<=i<n 实现过程时间 ...
- c语言 lis的nlogn算法,ACM竞赛高级算法讲义.doc
第9章动态规划初步 学习目标 ?理解状态和状态转移方程 ?理解最优子结构和重叠子问题 ?熟练运用递推法和记忆化搜索求解数字三角形问题 ?熟悉DAG上动态规划的常见思路.两种状态定义方法和刷表法 ?掌握 ...
最新文章
- 他们爬了7000家创业公司数据,发现这些领域没那么容易应用AI
- shell脚本输出菱形与等边三角形
- python getopts_linux bash shell 中getopts 命令 和 python 中 getopt 函数的比较总结
- Win32程序中使用Combo box控件
- 终极会话劫持工具SSClone
- Google Spanner:谷歌的全球分布式数据库
- Spring的REST服务发现性,第5部分
- C语言程序设计二期末考试,C语言程序设计期末考试试卷2.doc
- surface php老是用不了,surface pro7触摸屏没反应怎么办
- Spring IoC?看这篇文章就够了...
- android回收站目录详解,android - 如何在回收站适配器外部的回收站视图中获取当前商品的位置 - 堆栈内存溢出...
- a1 抛光等级spi_抛光等级对照表
- 使用ILSpy查看dll里的部分代码
- MSN的头像存放路径
- MATLAB | 比生命游戏更自由的生命游戏
- 任小龙 mysql笔记_任小龙java基础的Excel笔记(完整版)
- vue-waterfall2瀑布流使用及坑
- js 数组按奇偶拆分_js数组拆分问题
- druid数据源下 sqlserver 出现 对象名 'xxx' 无效
- Windows上使用ssh密钥连接Linux(以centos7为例)和Windows与Windows的免密钥连接
热门文章
- 《ASP.NET AJAX程序设计 第I卷 服务器端ASP.NET AJAX Extensions与ASP.NET AJAX Control Toolkit》目录(最终定稿)...
- 《Python股票量化交易从入门到实践》随书赠送“回测框架”的使用帮助
- Java 源码剖析(13)--MyBatis 使用了哪些设计模式?
- Vue组件选项props
- 使用 代码 读取 build.gradle 中的自定义配置信息
- android开发利用传感器实现微信的摇一摇功能
- c++primer学习笔记
- Web,Servlet,网络复习,超全,快来看
- 测试工程师等级评定细则
- 【web前端开发 | CSS】css元素的显示模式