(转载)最长递增子序列 O(NlogN)算法
原博文:传送门
最长递增子序列(Longest Increasing Subsequence)
下面我们简记为 LIS。
定义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。
下面一步一步试着找出它。
我们定义一个序列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)!
练习题目:POJ 2533
(转载)最长递增子序列 O(NlogN)算法的更多相关文章
- 最长递增子序列 O(NlogN)算法
转自:点击打开链接 最长递增子序列,Longest Increasing Subsequence 下面我们简记为 LIS. 排序+LCS算法 以及 DP算法就忽略了,这两个太容易理解了. 假设存在一个 ...
- 最长上升子序列O(nlogn)算法详解
最长上升子序列 时间限制: 10 Sec 内存限制:128 MB 题目描述 给定一个序列,初始为空.现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置.我们想知道此时最长上升子 ...
- hdu 5773 最长递增子序列 (nlogn)+贪心
The All-purpose Zero Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Oth ...
- 最长递增子序列(LIS)
最长递增子序列(Longest Increasing Subsequence) ,我们简记为 LIS. 题:求一个一维数组arr[i]中的最长递增子序列的长度,如在序列1,-1,2,-3,4,-5,6 ...
- LIS 最长递增子序列
一.最长公共子序列 经典的动态规划问题,大概的陈述如下: 给定两个序列a1,a2,a3,a4,a5,a6......和b1,b2,b3,b4,b5,b6.......,要求这样的序列使得c同时是这两个 ...
- 算法设计 - LCS 最长公共子序列&&最长公共子串 &&LIS 最长递增子序列
出处 http://segmentfault.com/blog/exploring/ 本章讲解:1. LCS(最长公共子序列)O(n^2)的时间复杂度,O(n^2)的空间复杂度:2. 与之类似但不同的 ...
- 最长递增子序列 LIS 时间复杂度O(nlogn)的Java实现
关于最长递增子序列时间复杂度O(n^2)的实现方法在博客http://blog.csdn.net/iniegang/article/details/47379873(最长递增子序列 Java实现)中已 ...
- 【LeetCode】300.最长递增子序列——暴力递归(O(n^3)),动态规划(O(n^2)),动态规划+二分法(O(nlogn))
算法新手,刷力扣遇到这题,搞了半天终于搞懂了,来这记录一下,欢迎大家交流指点. 题目描述: 给你一个整数数组 nums ,找到其中最长严格递增子序列的长度. 子序列是由数组派生而来的序列,删除(或不删 ...
- 算法实践--最长递增子序列(Longest Increasing Subsquence)
什么是最长递增子序列(Longest Increasing Subsquence) 对于一个序列{3, 2, 6, 4, 5, 1},它包含很多递增子序列{3, 6}, {2,6}, {2, 4, 5 ...
随机推荐
- Nodejs进阶:如何玩转子进程(child_process)
本文摘录自个人总结<Nodejs学习笔记>,更多章节及更新,请访问 github主页地址.欢迎加群交流,群号 197339705. 模块概览 在node中,child_process这个模 ...
- [BZOJ 2819]NIM(dfs序维护树上xor值)
题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2819 分析: 树上的nim游戏,关键就是要判断树上的一条链的异或值是否为0 这个题目有 ...
- ASimpleCache使用感受
一.简介 ASimpleCache只能作为一份教程,一个学习样板,不能当真把它当回事. 作者杨福海,Afinal框架也是他创造的. 可是我读ASimpleCache的900行代码时,发现各种难看,并且 ...
- 东大OJ-1040-Count-快速幂方法求解斐波那契-
Many ACM team name may be very funny,such as "Complier_Error","VVVVV".Oh,wait fo ...
- 使用delegate实现简单的查询功能
protected void imgbtnSearch_Click(object sender, System.Web.UI.ImageClickEventArgs e) { string keyWo ...
- Linux下解决用户不能执行sudo的方法
报错: xxx is not in the sudoers file. This incident will be reported. Linux默认没有为当前用户开启sudo权限! $ su $ ...
- JavaMelody监控SQL
前言 前面讲过了Javamelody的基本配置,这里简单的介绍下,如何使用Javamelody来监控JDBC以及SQL. 手码不易,转载请注明:xingoo 在网上搜索很多资料,仅有开源社区上的两篇帖 ...
- Ubuntu下tftp服务器的搭建
参考博客:http://blog.chinaunix.net/uid-26495963-id-3206829.html 1. 安装 $ apt-get install tftp-hpa tftpd-h ...
- 6.7-3将数组arr中索引值为2的元素替换为“bb”
package shuzu; import java.util.Arrays; public class TH { public static void main(String[] args) { / ...
- Shell配置_配置IP
1.setup 打开图形化页面 a) 选择网络配置 b) 选择设置配置 c) 选择第一个网卡 2.启动网卡(第一个网卡) vim /etc/sysconfig/network-s ...