问题描述:

  给出一个未排序队列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. 一个将当前目录下HEX文件的第一行数据删除的程序

    为什么要写这样一个函数 在使用SoftConsole开发M3程序时,生成的hex文件,必须要把第一行数据删除,才能在Libero中使用,所以写了这个小工具,这是2.0版本了,第一版是直接删除第一行数据 ...

  2. MYSQL之视图、触发器、事务

    一 视图 视图是一个虚拟表(非真实存在),其本质是[根据SQL语句获取动态的数据集,并为其命名],用户使用时只需使用[名称]即可获取结果集,可以将该结果集当做表来使用. 使用视图我们可以把查询过程中的 ...

  3. AndroidStudio更改包名

    最近开发一个项目 和以前开发的某一个功能类似 不想再重新搭建界面 从零开始去写... 就想把原来的项目copy一份 但是这样的话安装在手机中会把原来的项目覆盖掉 这是因为它们的applicationI ...

  4. AssetBundle一些问题

    AssetBundle划分过细的问题,比如每个资源都是AssetBundle. 加载IO次数过多,从而增大了硬件设备耗能和发热的压力: Unity 5.3 ~ 5.5 版本中,Android平台上在不 ...

  5. .net中 多线程 笔记(基础)

    1. 在进程中可以有多个线程同时执行代码.进程之间是相对独立的,一个进程无法访问另一个进程的数据(除非利用分布式计算方式),一个进程运行的失败也不会影响其他进程的运行,Windows系统就是利用进程把 ...

  6. 在vsphere6.5启用Tesla K80

    基础环境: vsphere6.5 VMware vCenter6.5 宝德服务器2750S Tesla K80 0x01 选择主机,配置→硬件→PCI设备→添加K80显卡 注意:1.添加完显卡后,主机 ...

  7. webpack3升级为webpack4

    写在前面的话:为什么要升级,因为公司目前的项目使用webpack3,但是因为是多页应用,入口估计有一百多个,开发模式下慢得不像话,修改一个文件需要十几秒才编译好,之前的解决方案是减少入口,但是要调试其 ...

  8. SICP读书笔记 2.2

    SICP CONCLUSION 让我们举起杯,祝福那些将他们的思想镶嵌在重重括号之间的Lisp程序员 ! 祝我能够突破层层代码,找到住在里计算机的神灵! 目录 1. 构造过程抽象 2. 构造数据抽象 ...

  9. ThinkPHP3.2开发仿京东商城项目实战视频教程

    ThinkPHP3.2仿京东商城视频教程实战课程,ThinkPHP3.2开发大型商城项目实战视频 第一天 1.项目说明 2.时间插件.XSS过滤.在线编辑器使用 3.商品的删除 4.商品的修改完成-一 ...

  10. webpack2.0+ vue2.0

    一 webpack 2.0 及用到的插件安装(默认已经有node环境) 1. package.json文件 (插件安装及插件的功能不详解) { "private": true, & ...