时间复杂度为 n*logn的LIS算法是用一个stack维护一个最长递增子序列

如果存在 x < y 且  a[x] > a[y],那么我们可以用a[y]去替换a[x]
因为a[y]比较小,具有更大的潜力,使得后面的元素和它成为更长的递增序列
如例子: a[] = {1,4,8,3,6};
我们用一个stack st保存当前的最长递增子序列,top = 0;
很明显,初始化时st[top] = 1;
之后随着i循环变量的递增,如果
a[i] > st[top] , 那么 st[++top] = a[i]. 很显然top+1就是当前最长递增子序列的长度
这样子判断的时间复杂度是O(1),
为什么可以这样子判断???
因为st保存的是当前的最长递增子序列,所以如果a[i] > st[top] 那么a[i]可以加入st中
从而形成更长的最长递增子序列。
那么可能会有想法是,如果数据是1 5 3 4,很明显,最长递增子序列是1 3 4,
但是根据上面的想法是 1 5 形成最长递增子序列。
 
别担心
下面介绍 当  a[i] < st[top]时的处理方法
上面我们说过, 如果存在x < y 且 a[x] > a[y] 我们可以使用a[y]去替换a[x]
因为a[y] 具有更大的潜力,使得后面的元素和它成为更长的递增序列。
所以当 a[i] < st[top]时, 显然 st中的元素就是a[x],而a[i]就是a[y]
我们在st中使用二分查找找到第一个大于等于a[i]的元素,然后用a[i]去替换它
比如 st = 1 , 4 , 8时
a[i] = 3,
我们可以用a[i]去替换4,从而在不影响结果的前提下,减少时间复杂度
 
 
题目uva10534
给定一个一组数字,要我们求这样一个序列
在序列的左边是递增的,右边是递减的,且递增和递减的个数要是一样的
思路:分别从两边进行最长递增子序列的dp,
    dp1是从下标 0 -> n-1   进行dp    
    dp2是从下标 n-1 -> 0   进行dp
    所以 ans = max{ min(dp1[i]-1, dp2[i]-1)+1, 0<=i<n };
    但是题目的数据有1w,O(N*N)的算法是不行的,
    所以要用nlogn的算法
 
 #include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
#include <iostream>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <string>
using namespace std;
typedef long long LL;
const int INF = <<;
const int N = + ;
int min(const int &a, const int &b)
{
return a < b ? a :b;
}
int max(const int &a, const int &b)
{
return a < b ? b : a;
}
int st[N];
int top;
void LIS(int *a, int n, int *dp)
{
int i,j;
top = ;
st[top] = a[];
for(i=; i<n; ++i)
{
if(a[i] > st[top])
{
st[++top] = a[i];
dp[i] = top + ;
}
else
{
int low = , high = top;
while(low <= high)
{
int mid = (low + high) >> ;
if(st[mid]<a[i])
low = mid + ;
else
high = mid - ;
}
st[low] = a[i];
dp[i] = low +;
}
}
}
int a[N];
int dp[][N];
int main()
{
int n,i,j;
while(scanf("%d",&n)!=EOF)
{
for(i=; i<n; ++i)
{
scanf("%d",&a[i]);
dp[][i] = dp[][i] = ;
}
LIS(a,n,dp[]); int low = ,high = n - ;
while(low < high)
{
int t = a[low];
a[low] = a[high];
a[high] = t;
low ++;
high --;
}
LIS(a,n,dp[]); int ans = ;
for(i=; i<n; ++i)
{
int t = * min(dp[][i]-,dp[][n-i-]-) +;//因为第二次dp是将数组倒过来dp,所以要n-i-1
ans = max(ans,t);
}
printf("%d\n",ans);
}
return ;
}


 

时间复杂度为O(nlogn)的LIS算法的更多相关文章

  1. 时间复杂度为O(nlogn)的排序算法

    时间复杂度为O(nlogn)的排序算法(归并排序.快速排序),比时间复杂度O(n²)的排序算法更适合大规模数据排序. 归并排序 归并排序的核心思想 采用"分治思想",将要排序的数组 ...

  2. 平均时间复杂度为O(nlogn)的排序算法

    本文包括 1.快速排序 2.归并排序 3.堆排序 1.快速排序 快速排序的基本思想是:采取分而治之的思想,把大的拆分为小的,每一趟排序,把比选定值小的数字放在它的左边,比它大的值放在右边:重复以上步骤 ...

  3. 算法心得1:由$nlogn$复杂度的LIS算法引起的思考

    LIS(Longest Increasing Subsequence)是一类典型的动态规划类问题,简化描述如下: 给定$N(n) = \{1,2...,n\}$的一个排列$P(n)$,求$P(n)$中 ...

  4. N种方法妙讲LIS算法

    LIS算法经典汇总 假设存在一个序列d[1..9] = 2 1 5 3 6 4 8 9 7,可以看出来它的LIS长度为5.下面一步一步试着找出它.我们定义一个序列B,然后令 i = 1 to 9 逐个 ...

  5. 备战秋招之十大排序——O(nlogn)级排序算法

    时间复杂度O(nlogn)级排序算法 五.希尔排序 首批将时间复杂度降到 O(n^2) 以下的算法之一.虽然原始的希尔排序最坏时间复杂度仍然是O(n^2),但经过优化的希尔排序可以达到 O(n^{1. ...

  6. java实现LIS算法,出操队形问题

    假设有序列:2,1,3,5,求一个最长上升子序列就是2,3,5或者1,3,5,长度都为3. LIS算法的思想是: 设存在序列a. ① 如果只有一个元素,那么最长上升子序列的长度为1: ② 如果有两个元 ...

  7. 最大子序列和问题--时间复杂度O(NlogN)

    最大子序列和问题--时间复杂度O(NlogN) package a; /* * 最大子序列和问题,时间复杂度O(NlogN) */ public class Sequence { private st ...

  8. LeetCode 42. Trapping Rain Water 【两种解法】(python排序遍历,C++ STL map存索引,时间复杂度O(nlogn))

    LeetCode 42. Trapping Rain Water Python解法 解题思路: 本思路需找到最高点左右遍历,时间复杂度O(nlogn),以下为向左遍历的过程. 将每一个点的高度和索引存 ...

  9. 最长上升子序列算法(n^2 及 nlogn) (LIS) POJ2533Longest Ordered Subsequence

    问题描述: 一个数的序列bi,当b1 < b2 < ... < bS的时候,我们称这个序列是上升的.对于给定的一个序列(a1, a2, ..., aN),我们可以得到一些上升的子序列 ...

随机推荐

  1. java中遍历MAP,嵌套map的几种方法

    java中遍历MAP的几种方法 Map<String,String> map=new HashMap<String,String>();    map.put("us ...

  2. iOS高效开源类库

    因为iOS SDK相对比较底层,所以开发者就得受累多做一些体力活.不过幸运的是,有很多第三方的类库可以用来简化很多不必要的工作.笔者整理了一下在本人学习过程中用到的一些比较有用Objective-C开 ...

  3. 名字修饰约定extern "C"与extern "C++"浅析

    所谓名字修饰约定,就是指变量名.函数名等经过编译后重新输出名称的规则. 比如源代码中函数名称为int Func(int a,int b),经过编译后名称可能为?Func@@YAHHH@Z.?Func@ ...

  4. linux route命令的使用详解

    route命令用于显示和操作IP路由表.要实现两个不同的子网之间的通信,需要一台连接两个网络的路由器,或者同时位于两个网络的网关来实现.在Linux系统中,设置路由通常是 为了解决以下问题:该Linu ...

  5. pptv web前端面试题

    今天上午一考完试,就一直等待pptv的电话,结果下午就收到了pptv的通知(pptv的效率还是很不错的,之前面试官和我说在一到两周之内给回复,结果过了7天就给回复了,赞一个)因为我面试的是web前端( ...

  6. 奋斗的孩子的TableView(三篇文章)

    http://blog.sina.com.cn/s/blog_a6fb6cc90101i8it.html http://blog.sina.com.cn/s/blog_a6fb6cc90101hhse ...

  7. deque,list,queue,priority_queue

    1.deque deque双端队列容器与vector一样,采用线性表顺序存储结构,但与vector唯一不同的是,deque采用分块的线性存储结构来存 储数据,每块的大小一般为512字节,称为一个deq ...

  8. SPOJ 7001(莫比乌斯反演)

    传送门:Visible Lattice Points 题意:0<=x,y,z<=n,求有多少对xyz满足gcd(x,y,z)=1. 设f(d) = GCD(a,b,c) = d的种类数 : ...

  9. php学习之道:WSDL具体解释(三)

    通过声明方式定义绑定(binding)属性 假设你在服务中採用SOAP binding.你能够使用JAX-WS来指定一定数量的属性binding. 这些属性指定相应你在WSDL中指定的属性.某些设置. ...

  10. 属性“dataProvider”有多个初始值设定项。(注意:“dataProvider”是“mx.charts.BarChart”的默认属性)。

    1.错误描写叙述 属性"dataProvider"有多个初始值设定项.(注意:"dataProvider"是"mx.charts.BarChart&q ...