Longest Increasing Subsequence的两种解法
问题描述:
给出一个未排序队列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的两种解法的更多相关文章
- Longest Increasing Subsequence的两种算法
问题描述:给出一个序列a1,a2,a3,a4,a5,a6,a7-.an,求它的一个子序列(设为s1,s2,-sn),使得这个子序列满足这样的性质,s1<s2<s3<-<sn并且 ...
- [LeetCode] Longest Increasing Subsequence 最长递增子序列
Given an unsorted array of integers, find the length of longest increasing subsequence. For example, ...
- 最长上升子序列 LIS(Longest Increasing Subsequence)
引出: 问题描述:给出一个序列a1,a2,a3,a4,a5,a6,a7….an,求它的一个子序列(设为s1,s2,…sn),使得这个子序列满足这样的性质,s1<s2<s3<…< ...
- Longest Increasing Subsequence - LeetCode
Given an unsorted array of integers, find the length of longest increasing subsequence. For example, ...
- [LeetCode] 300. Longest Increasing Subsequence 最长递增子序列
Given an unsorted array of integers, find the length of longest increasing subsequence. Example: Inp ...
- [tem]Longest Increasing Subsequence(LIS)
Longest Increasing Subsequence(LIS) 一个美丽的名字 非常经典的线性结构dp [朴素]:O(n^2) d(i)=max{0,d(j) :j<i&& ...
- [LintCode] Longest Increasing Subsequence 最长递增子序列
Given a sequence of integers, find the longest increasing subsequence (LIS). You code should return ...
- Leetcode 300 Longest Increasing Subsequence
Given an unsorted array of integers, find the length of longest increasing subsequence. For example, ...
- [LeetCode] Number of Longest Increasing Subsequence 最长递增序列的个数
Given an unsorted array of integers, find the number of longest increasing subsequence. Example 1: I ...
随机推荐
- cogs 1330 [HNOI2008]玩具装箱toy
cogs 1330 [HNOI2008]玩具装箱toy 瞎扯,急忙AC的请跳过 感觉数据结构写的太多了有点晕=+ 发现还没学斜率优化+- 于是来学一学QwQ 上次这题打了个决策优化直接水过了..理论O ...
- ubuntu 图形化界面 gui 桌面版 root登录 sorry,that didn't work.please try again! 抱歉,认证失败。请重试
出现这种问题,用下面的方法就行了 https://jingyan.baidu.com/article/bad08e1e224b2709c85121f1.html 而且我发现,因为我用的是英文版的ubu ...
- 菜鸟vimer成长记——第2.3章、insert模式
大部分的Vim 命令都在非插入模式中执行,不过有些功能在插入模式中会更好实现些. 如果没有输入当前文件不存在的新文本的需求时,建议通过其他模式来操作完成. 目的 掌握inser模式下常用操作的语法和概 ...
- DMS路由表
DMS路由表: route add -p 53.90.146.0 mask 255.255.255.0 10.77.35.249 ================================= ...
- SpringBoot之MongoTemplate的查询可以怎么耍
学习一个新的数据库,一般怎么下手呢?基本的CURD没跑了,当可以熟练的增.删.改.查一个数据库时,可以说对这个数据库算是入门了,如果需要更进一步的话,就需要了解下数据库的特性,比如索引.事物.锁.分布 ...
- Java实现斗地主发牌(Collections工具类的应用)
package com.doudou_01; import java.util.ArrayList; import java.util.Collections; import java.util.Li ...
- VM虚拟机安装CentOS 7.0添加jdk环境
虚拟机注册码 5A02H-AU243-TZJ49-GTC7K-3C61N 安装centos系统,网络类型选择桥接网络安装完成后vi /etc/sysconfig/network-scripts/ifc ...
- 《杜增强讲Unity之Tanks坦克大战》3-添加坦克
3 添加坦克 3.1 本节效果预览 3.2 另存新场景 首先打开上次的场景s1,另存为s2,放到同一个文件夹下面. 3.3 添加坦克模型 在Model文件夹下面找到Tank模型 将Tank ...
- Netty源码分析第7章(编码器和写数据)---->第4节: 刷新buffer队列
Netty源码分析第七章: 编码器和写数据 第四节: 刷新buffer队列 上一小节学习了writeAndFlush的write方法, 这一小节我们剖析flush方法 通过前面的学习我们知道, flu ...
- Python3中的函数 大全
Python 函数 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复利用率.Python提供了许多内建函数,比如print().但也可以自己创建 ...