N种方法妙讲LIS算法
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 最少拦截系统
怎么办呢?多搞几套系统呗!你说说倒蛮容易,成本呢?成本是个大问题啊.所以俺就到这里来求救了,请帮助计算一下最少需要多少套拦截系统.
给定排好序的一堆数列中,求其的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算法的更多相关文章
- 三种方法实现PCA算法(Python)
主成分分析,即Principal Component Analysis(PCA),是多元统计中的重要内容,也广泛应用于机器学习和其它领域.它的主要作用是对高维数据进行降维.PCA把原先的n个特征用数目 ...
- Python使用三种方法实现PCA算法[转]
主成分分析(PCA) vs 多元判别式分析(MDA) PCA和MDA都是线性变换的方法,二者关系密切.在PCA中,我们寻找数据集中最大化方差的成分,在MDA中,我们对类间最大散布的方向更感兴趣. 一句 ...
- C# 移动无标题栏窗体的几种方法
第一种,手工移动. 该方法根据鼠标位置实现窗体的移动.网上有很多相关的例子,这里不再多讲. 第二种,调用系统API原理:是当鼠标左键按下时,让系统认为是在标题栏按下的.这里我们用到了winapi里的W ...
- Microsoft.VisualBasic.dll的妙用and 改善C#公共程序类库质量的10种方法
Microsoft.VisualBasic.dll的妙用(开发中肯定会用到哦) 前言 做过VB开发的都知道,有一些VB里面的好的函数在.NET里面都没有,而Microsoft.VisualBasic. ...
- 趣味算法:字符串反转的N种方法(转)
老赵在反对北大青鸟的随笔中提到了数组反转.这的确是一道非常基础的算法题,然而也是一道很不平常的算法题(也许所有的算法深究下去都会很不平常).因为我写着写着,就写出来8种方法……现在我们以字符串的反转为 ...
- 两种方法实现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( ...
- 【机器学习算法-python实现】协同过滤(cf)的三种方法实现
(转载请注明出处:http://blog.csdn.net/buptgshengod) 1.背景 协同过滤(collaborative filtering)是推荐系统经常使用的一种方法.c ...
- 转载 50种方法优化SQL Server数据库查询
原文地址 http://www.cnblogs.com/zhycyq/articles/2636748.html 50种方法优化SQL Server数据库查询 查询速度慢的原因很多,常见如下几种: 1 ...
- Java获取随机数的几种方法
Java获取随机数的几种方法 .使用org.apache.commons.lang.RandomStringUtils.randomAlphanumeric()取数字字母随机10位; //取得一个3位 ...
随机推荐
- Python 异步IO、IO多路复用
事件驱动模型 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UT ...
- Cookie知识点小结
问题是什么?有哪些技术?如何解决? 1. Cookie 1)完成回话跟踪的一种机制:采用的是在客户端保存Http状态信息的方案 2)Cookie是在浏览器访问WEB服务器的某个资源时,由WEB服务器在 ...
- android 推断Apk是否签名和 签名是否一致
推断Apk是否签名 用命令:jarsigner -verify -verbose -certs <apk文件> 假设有Android Debug字樣就是debug 假设已经签名: [证书的 ...
- poj1330Nearest Common Ancestors(LCA小结)
题目请戳这里 题目大意:意如其名. 题目分析:本题只有一个查询,所以可以各种乱搞过去. 不过对于菜鸟而言,还是老老实实练习一下LCA算法. LCA有很多经典的算法.按工作方式分在线和离线2种. tar ...
- servlet核心API的UML图
- Oracle INTERVAL DAY TO SECOND数据类型
INTERVAL DAY TO SECOND数据类型 Oracle语法: INTERVAL '{ integer | integer time_expr | time_expr }' { { DAY ...
- [Python学习笔记][第四章Python字符串]
2016/1/28学习内容 第四章 Python字符串与正则表达式之字符串 编码规则 UTF-8 以1个字节表示英语字符(兼容ASCII),以3个字节表示中文及其他语言,UTF-8对全世界所有国家需要 ...
- 20. Screen
一. Screen 1.什么是Screen Screen 是在多个进程间多路复用一个物理终端的全屏窗口管理器,Screen 也叫会话,一个Screen 会话中可以有多个 Screen 窗口, ...
- spring aop获取目标对象的方法对象(包括方法上的注解)
这两天在学习权限控制模块.以前看过传智播客黎活明老师的巴巴运动网视频教程,里面就讲到权限控制的解决方案,当时也只是看看视频,没有动手实践,虽说看过几遍,可是对于系统中的权限控制还是很迷茫,所以借着这次 ...
- Silverlight Application 无法调用js的方法
今天下午做项目的时候遇到了这个错误 找了很多原因没找出,在蛋疼之际找出了问题, Silverlight调js方法的时候 js方法里面不能出现一点问题,如果有一点问题就会报这个错误.