LIS算法经典汇总

假设存在一个序列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)~!
借助例题

hdu 1257 最少拦截系统

Problem Description
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能超过前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹.
怎么办呢?多搞几套系统呗!你说说倒蛮容易,成本呢?成本是个大问题啊.所以俺就到这里来求救了,请帮助计算一下最少需要多少套拦截系统.
 
Input
输入若干组数据.每组数据包括:导弹总个数(正整数),导弹依此飞来的高度(雷达给出的高度数据是不大于30000的正整数,用空格分隔)
 
Output
对应每组数据输出拦截所有导弹最少要配备多少套这种导弹拦截系统.
 
Sample Input
8 389 207 155 300 299 170 158 65
 
Sample Output
2
经典LIS算法,与求最大上升子序列相似:
以数组 h[] 记录拦截系统当前的拦截高度,先初始化为最大值 INF = 30000+10,
表示每一个新拦截系统都能拦截所有的导弹,然后遇到一个导弹就往前找看是否有已经使用了的系统能拦截,如果有,直接用;否则重新弄一个系统。最后再看用了几个系统就好了。
 
第一个导弹 389 < h[1] ( h[1] = INF)被第一个系统拦截 h[1] = 389
第二个导弹 207 < h[1] 被第一个系统拦截 h[1] = 207
第三个导弹 155 < h[1] h[1] = 155
第四个导弹 300 > h[1] , 300 < h[2] ( h[2] = INF ) 所以新开发一个系统拦截第四个导弹, h[2] = 300
第五个导弹 299 > h[1] , 299 < h[2] 被第二个系统拦截 h[2] = 299
第六个导弹 170 > h[1] , 170 < h[2] h[2] = 170
第七个导弹 158 > h[1] , 158 < h[2] h[2] = 158
第八个导弹 65 < h[1] 被第一个系统拦截 h[1] = 65
 
所以最后使用了两个系统就拦截了所有的导弹【遍历 h[]数组从 1到 n 看有几个 != INF 就说明使用了】
 
导弹高度:389 207 155 300 299 170 158 65
使用的拦截系统: 1 1 1 2 2 2 2 1
 求最长上升子序列:

给定排好序的一堆数列中,求其的LIS长度。它的LIS长度就是它非上升子序列的个数。

此题可以用N种方法讲解,下面一一为大家讲解:

方法一:DP解法:

 #include<stdio.h>
#define MAX(x,y) x>y?x:y
int dp[],missile[];
int main(){
int N,max;
while(~scanf("%d",&N)){max=;
for(int i=;i<N;++i){dp[i]=;
scanf("%d",&missile[i]);
for(int j=;j<i;j++){
if(missile[j]<missile[i])dp[i]=MAX(dp[j]+,dp[i]);
}
max=MAX(max,dp[i]);
}
printf("%d\n",max);
}
return ;
}

方法二:

二分法+贪心:

 #include<stdio.h>
int missile[],Lis[];
int r;
void search(int x){
int left=,mid,right=r;
while(left<=right){
mid=(left+right)/;//把 / 换成 >> 老是陷入死循环。。。。。
if(Lis[mid]<x)left=mid+;
else right=mid-;
}
Lis[left]=x;
}
int main(){
int N;
while(~scanf("%d",&N)){r=;
scanf("%d",&missile[]);Lis[r]=missile[];
for(int i=;i<N;i++){
scanf("%d",&missile[i]);
if(missile[i]>Lis[r])Lis[++r]=missile[i];
else search(missile[i]);
}
printf("%d\n",r);
}
return ;
}

方法三:

STL+二分+贪心:

 #include<stdio.h>
#include<algorithm>
using namespace std;
int Lis[];
int main(){
int N,r,x;
while(~scanf("%d",&N)){r=;
scanf("%d",&x);
Lis[r]=x;
for(int i=;i<N;++i){
scanf("%d",&x);
if(x>Lis[r])Lis[++r]=x;
else *lower_bound(Lis,Lis+r,x)=x;
}
printf("%d\n",r+);
}
return ;
}

方法四:

vector+二分+贪心:

 #include<stdio.h>
#include<vector>
#include<algorithm>
using namespace std;
int main(){
int N,x;
while(~scanf("%d",&N)){
vector<int>Lis;vector<int>::iterator iter;
while(N--){
scanf("%d",&x);
iter=lower_bound(Lis.begin(),Lis.end(),x);
if(iter==Lis.end())Lis.push_back(x);
else *iter=x;
}
printf("%d\n",Lis.size());
}
return ;
}

N种方法妙讲LIS算法的更多相关文章

  1. 三种方法实现PCA算法(Python)

    主成分分析,即Principal Component Analysis(PCA),是多元统计中的重要内容,也广泛应用于机器学习和其它领域.它的主要作用是对高维数据进行降维.PCA把原先的n个特征用数目 ...

  2. Python使用三种方法实现PCA算法[转]

    主成分分析(PCA) vs 多元判别式分析(MDA) PCA和MDA都是线性变换的方法,二者关系密切.在PCA中,我们寻找数据集中最大化方差的成分,在MDA中,我们对类间最大散布的方向更感兴趣. 一句 ...

  3. C# 移动无标题栏窗体的几种方法

    第一种,手工移动. 该方法根据鼠标位置实现窗体的移动.网上有很多相关的例子,这里不再多讲. 第二种,调用系统API原理:是当鼠标左键按下时,让系统认为是在标题栏按下的.这里我们用到了winapi里的W ...

  4. Microsoft.VisualBasic.dll的妙用and 改善C#公共程序类库质量的10种方法

    Microsoft.VisualBasic.dll的妙用(开发中肯定会用到哦) 前言 做过VB开发的都知道,有一些VB里面的好的函数在.NET里面都没有,而Microsoft.VisualBasic. ...

  5. 趣味算法:字符串反转的N种方法(转)

    老赵在反对北大青鸟的随笔中提到了数组反转.这的确是一道非常基础的算法题,然而也是一道很不平常的算法题(也许所有的算法深究下去都会很不平常).因为我写着写着,就写出来8种方法……现在我们以字符串的反转为 ...

  6. 两种方法实现Python二分查找算法

    两种方法实现Python二分查找算法   一. ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 arr=[1,3,6,9,10,20,30] def findnumber( ...

  7. 【机器学习算法-python实现】协同过滤(cf)的三种方法实现

    (转载请注明出处:http://blog.csdn.net/buptgshengod) 1.背景       协同过滤(collaborative filtering)是推荐系统经常使用的一种方法.c ...

  8. 转载 50种方法优化SQL Server数据库查询

    原文地址 http://www.cnblogs.com/zhycyq/articles/2636748.html 50种方法优化SQL Server数据库查询 查询速度慢的原因很多,常见如下几种: 1 ...

  9. Java获取随机数的几种方法

    Java获取随机数的几种方法 .使用org.apache.commons.lang.RandomStringUtils.randomAlphanumeric()取数字字母随机10位; //取得一个3位 ...

随机推荐

  1. Python 异步IO、IO多路复用

    事件驱动模型 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UT ...

  2. Cookie知识点小结

    问题是什么?有哪些技术?如何解决? 1. Cookie 1)完成回话跟踪的一种机制:采用的是在客户端保存Http状态信息的方案 2)Cookie是在浏览器访问WEB服务器的某个资源时,由WEB服务器在 ...

  3. android 推断Apk是否签名和 签名是否一致

    推断Apk是否签名 用命令:jarsigner -verify -verbose -certs <apk文件> 假设有Android Debug字樣就是debug 假设已经签名: [证书的 ...

  4. poj1330Nearest Common Ancestors(LCA小结)

    题目请戳这里 题目大意:意如其名. 题目分析:本题只有一个查询,所以可以各种乱搞过去. 不过对于菜鸟而言,还是老老实实练习一下LCA算法. LCA有很多经典的算法.按工作方式分在线和离线2种. tar ...

  5. servlet核心API的UML图

  6. Oracle INTERVAL DAY TO SECOND数据类型

    INTERVAL DAY TO SECOND数据类型 Oracle语法: INTERVAL '{ integer | integer time_expr | time_expr }' { { DAY ...

  7. [Python学习笔记][第四章Python字符串]

    2016/1/28学习内容 第四章 Python字符串与正则表达式之字符串 编码规则 UTF-8 以1个字节表示英语字符(兼容ASCII),以3个字节表示中文及其他语言,UTF-8对全世界所有国家需要 ...

  8. 20. Screen

    一. Screen 1.什么是Screen     Screen 是在多个进程间多路复用一个物理终端的全屏窗口管理器,Screen 也叫会话,一个Screen 会话中可以有多个 Screen 窗口, ...

  9. spring aop获取目标对象的方法对象(包括方法上的注解)

    这两天在学习权限控制模块.以前看过传智播客黎活明老师的巴巴运动网视频教程,里面就讲到权限控制的解决方案,当时也只是看看视频,没有动手实践,虽说看过几遍,可是对于系统中的权限控制还是很迷茫,所以借着这次 ...

  10. Silverlight Application 无法调用js的方法

    今天下午做项目的时候遇到了这个错误 找了很多原因没找出,在蛋疼之际找出了问题, Silverlight调js方法的时候 js方法里面不能出现一点问题,如果有一点问题就会报这个错误.