问题描述:

  给出一个未排序队列nums,如[10, 9, 2, 5, 3, 7, 101, 18]。找出其中最长的增长序列,但不是连续增长序列,如[2, 3, 7, 101]就是对应的最长增长序列LIS,因为序列不唯一,所以要求返回的是长度,如4.

一.动态规划 O(n^2):

  比较容易想到的就是复杂度为O(n^2)的算法。这是一个备忘录算法,也是动态规划算法。需要建立一个备忘录dp,备忘录dp[i]记录序列从下标0到下标i最长的子序列长度。对于dp[j]的值则需要在nums序列红中找到0到(j-1)所有比nums[j]小元素,并在这些元素中选择备忘录dp值最大的一个如dp[k],则dp[j]=dp[k]+1;

public int lengthOfLIS(int[] nums) {
if(nums==null || nums.length==0)
return 0;
int[] bigLength=new int[nums.length];
for(int i=0;i<nums.length;i++) bigLength[i]=1;
int maxLength=1;
for(int i=1;i<nums.length;i++){
    //从前面找到比 nums[i]小,且dp值最大的那个。加1便是当前的值
for(int j=0;j<i;j++){
if(nums[j]<nums[i])
bigLength[i]=Math.max(bigLength[j]+1,bigLength[i]);
} maxLength=Math.max(bigLength[i],maxLength);
}
return maxLength;
}

二 .二分法查找O(nlg(n))

  首先建立一个栈stack来存储遍历到当前时刻 i 的一个最长递增序列(栈内是递增序列,但概念和题目中的递增序列不同)。设当前时刻为 i 则

1.如果元素 i 比栈顶元素大则入栈,stack[top++]=nums[i+1];

2.如果元素 i 比栈顶元素小,则在栈中采用二分查找法找到一个位置j 替换成当前元素nums[i] 。 该做法的目的是如果出现小元素就往栈内部替换,当前替换的结果影响下一次的替换,特别是栈顶元素。栈顶元素的替换需要比较stack[top],stack[top--]及nums[i]三个的值。

3.最后输出 栈的长度。

public int lengthOfLIS(int[] nums) {
if(nums==null || nums.length==0)
return 0; int[] stack= new int[nums.length];
int top=0; for(int num:nums){
if(top==0 || stack[top-1]<num) stack[top++]=num;
else{
  //如果在栈中没有对应的元素,则将找到的插入坐标为 j 返回-j-1. 如果找到则返回对应的坐标位置。
int i=Arrays.binarySearch(dp,0,top,num);
i= i<0? -i-1:i;
dp[i]=num;
}
}
return top;
}

   另外网上有关于只用栈没用利用二分法查找法的做法,使得复杂度变为O(n),试了下是不行的。他大概的思路是:

1.如果当前栈为空或栈顶元素小于当前元素nums[i],则入栈

2.如果nums[i]<stack[top] 且 nums[i]>stack[top-1] 则替换栈顶元素,stack[top]=nums[i]。

这种做法忽略了stack[top-1]之前的元素对stack[top-1]的影响。算法代码如下:

public int lengthOfLIS(int[] nums) {
int len=nums.length;
Stack<Integer> stack=new Stack<Integer>();
for(int i=len-1; i>=0; i--)
{
if(stack.isEmpty())
{
stack.push(nums[i]);
}else
{
int val= stack.pop();
if(stack.isEmpty())
{
if(nums[i]>=val)
{
val=nums[i];
}else
{
stack.push(val);
val=nums[i];
}
}else
{
int up=stack.peek();
if(nums[i]<val)
{
stack.push(val);
val=nums[i];
}else if(nums[i]>val && nums[i]<up)
{
val=nums[i];
}
}
stack.push(val);
}
}
return stack.size();
}

Longest Increasing Subsequence的两种解法的更多相关文章

  1. Longest Increasing Subsequence的两种算法

    问题描述:给出一个序列a1,a2,a3,a4,a5,a6,a7-.an,求它的一个子序列(设为s1,s2,-sn),使得这个子序列满足这样的性质,s1<s2<s3<-<sn并且 ...

  2. [LeetCode] Longest Increasing Subsequence 最长递增子序列

    Given an unsorted array of integers, find the length of longest increasing subsequence. For example, ...

  3. 最长上升子序列 LIS(Longest Increasing Subsequence)

    引出: 问题描述:给出一个序列a1,a2,a3,a4,a5,a6,a7….an,求它的一个子序列(设为s1,s2,…sn),使得这个子序列满足这样的性质,s1<s2<s3<…< ...

  4. Longest Increasing Subsequence - LeetCode

    Given an unsorted array of integers, find the length of longest increasing subsequence. For example, ...

  5. [LeetCode] 300. Longest Increasing Subsequence 最长递增子序列

    Given an unsorted array of integers, find the length of longest increasing subsequence. Example: Inp ...

  6. [tem]Longest Increasing Subsequence(LIS)

    Longest Increasing Subsequence(LIS) 一个美丽的名字 非常经典的线性结构dp [朴素]:O(n^2) d(i)=max{0,d(j) :j<i&& ...

  7. [LintCode] Longest Increasing Subsequence 最长递增子序列

    Given a sequence of integers, find the longest increasing subsequence (LIS). You code should return ...

  8. Leetcode 300 Longest Increasing Subsequence

    Given an unsorted array of integers, find the length of longest increasing subsequence. For example, ...

  9. [LeetCode] Number of Longest Increasing Subsequence 最长递增序列的个数

    Given an unsorted array of integers, find the number of longest increasing subsequence. Example 1: I ...

随机推荐

  1. cogs 1330 [HNOI2008]玩具装箱toy

    cogs 1330 [HNOI2008]玩具装箱toy 瞎扯,急忙AC的请跳过 感觉数据结构写的太多了有点晕=+ 发现还没学斜率优化+- 于是来学一学QwQ 上次这题打了个决策优化直接水过了..理论O ...

  2. ubuntu 图形化界面 gui 桌面版 root登录 sorry,that didn't work.please try again! 抱歉,认证失败。请重试

    出现这种问题,用下面的方法就行了 https://jingyan.baidu.com/article/bad08e1e224b2709c85121f1.html 而且我发现,因为我用的是英文版的ubu ...

  3. 菜鸟vimer成长记——第2.3章、insert模式

    大部分的Vim 命令都在非插入模式中执行,不过有些功能在插入模式中会更好实现些. 如果没有输入当前文件不存在的新文本的需求时,建议通过其他模式来操作完成. 目的 掌握inser模式下常用操作的语法和概 ...

  4. DMS路由表

    DMS路由表: route add -p 53.90.146.0 mask 255.255.255.0 10.77.35.249   ================================= ...

  5. SpringBoot之MongoTemplate的查询可以怎么耍

    学习一个新的数据库,一般怎么下手呢?基本的CURD没跑了,当可以熟练的增.删.改.查一个数据库时,可以说对这个数据库算是入门了,如果需要更进一步的话,就需要了解下数据库的特性,比如索引.事物.锁.分布 ...

  6. Java实现斗地主发牌(Collections工具类的应用)

    package com.doudou_01; import java.util.ArrayList; import java.util.Collections; import java.util.Li ...

  7. VM虚拟机安装CentOS 7.0添加jdk环境

    虚拟机注册码 5A02H-AU243-TZJ49-GTC7K-3C61N 安装centos系统,网络类型选择桥接网络安装完成后vi /etc/sysconfig/network-scripts/ifc ...

  8. 《杜增强讲Unity之Tanks坦克大战》3-添加坦克

    3 添加坦克 3.1 本节效果预览   3.2 另存新场景 首先打开上次的场景s1,另存为s2,放到同一个文件夹下面.   3.3 添加坦克模型 在Model文件夹下面找到Tank模型   将Tank ...

  9. Netty源码分析第7章(编码器和写数据)---->第4节: 刷新buffer队列

    Netty源码分析第七章: 编码器和写数据 第四节: 刷新buffer队列 上一小节学习了writeAndFlush的write方法, 这一小节我们剖析flush方法 通过前面的学习我们知道, flu ...

  10. Python3中的函数 大全

    Python 函数 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复利用率.Python提供了许多内建函数,比如print().但也可以自己创建 ...