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位 ...
随机推荐
- 一个简陋的 CSS 样式
有些网友对 Smart Framewok 中的 Sample 示例的样式比较感兴趣.由于本人对前端不太精通,但为了满足网友们的需求,只好献丑了. 以下这个简陋的 CSS 样式: ? 1 2 3 4 5 ...
- 编程算法 - 圆圈中最后剩下的数字(递推公式) 代码(C++)
圆圈中最后剩下的数字(递推公式) 代码(C++) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 0,1...,n-1这n个数字排成一个圆圈, 从数字0開始 ...
- MP3文件结构及解码概述
MP3文件结构概述 Layer-3音频文件.MPEG(MovingPicture Experts Group)在汉语中译为活动图像专家组,特指活动影音压缩标准,MPEG音频文件是MPEG1标准中的声音 ...
- Android界面优化方法
我们在推出一款APP之后,中间出现了一些体验上的问题,一个明显的是界面卡顿,针对此问题我们采取了如下的一些措施,起到了一些效果. 1.优化界面层次 针对可以合并的界面层次进行合并,减少界面的渲染,这个 ...
- Oralce 按分隔符把一列转成多行
1.前言 最近因项目需求,需要把员工的工作组返回给前台,但是数据库是把员工的工作组Id,都存在一个字段内了(以“逗号”分隔),而这样不符合前台的需要,他们需要一行,一行的数据.如: 数据库: user ...
- C#中Thread.Join()的理解
最近在项目中使用多线程,但是对多线程的一些用法和概念还有有些模棱两可,为了搞清楚查阅了一写资料,写下这篇日志加深理解吧. Thread.Join()在MSDN中的解释很模糊:Blocks the ca ...
- 1.想写一些关于c++的东西了,就作为个开篇吧
又再一次重拾c++,想写一些东西,给自己看看,不想再看一些隐晦翻译的外国书籍了,就从一本好读的书开始写一写. 就这本吧, <我的第一本C++书>> 来写一写自己的东西.
- 如何中途停止RMAN备份任务
问题背景 如果,你负责的数据库服务器,在RMAN进行全备时,业务又有大量数据要处理,一时间,系统资源直接被耗尽,影响到了业务的正常,你准备怎么处理? 解决办法 [不推荐]当时我们组的另外一个同事在没有 ...
- SQL语句 打印等腰三角形,菱形
) BEGIN 5 SET @S='' 8 BEGIN -@I) 10 BEGIN SET @S=@S+' ' END ELSE 14 BEGIN SET @S=@S+'**' 16 END END ...
- read/load
ready先执行,load后执行. DOM文档加载的步骤: (1) 解析HTML结构. (2) 加载外部脚本和样式表文件. (3) 解析并执行脚本代码. (4) 构造HTML DOM模型.//read ...