题目

例:arr=[2,1,5,3,6,4,8,9,7] ,最长递增子序列为1,3,4,8,9

题解

step1:找最长连续子序列长度

  • dp[]存以arr[i]结尾的情况下,arr[0..i]中的最长递增子序列的长度。
  • 额外加一个ends[]数组,初始化ends[0]=arr[0],其他为0。有一个有效区ends[0,r],只有有效区内的数才有意义。ends[i]=num表示遍历到目前,所有长度i+1的递增序列中,结尾最小的数时num。
  • 遍历arr[i]时,在ends有效区找最左边>=arr[i]的数,从左到右找的过程表示能连在arr[i]前的连续序列的长度在不断增加。
    • 若找到,记为ends[j],说明ends[j]及其后面的数都大于arr[I],故则dp[i]=j+1,ends[j]更新
    • 若没找到,说明ends[]有效区的数都比arr[i]小,故dp[i]=有效区长度+1,有效区右边界r++,ends[r]更新。
  • 因为ens[]是一个非递减序列,所以可以使用二分查找
  • 时间复杂度O(nlogn)

    step2:输出最长连续子序列元素

    找到dp[]中存储的值=最长长度的元素,记为dp[i]对应的arr[i]即为最后一个元素。再往前找存储的值=最长长度-1&&对应的arr[j]<arr[i]的位置,即为倒数第二元素...

其他

  • 这道题用到很经典的一种二分查找:找第一个比给定值大的元素的二分查找。
  • 最终一定是l=r=mid,那么当最后一个元素大于所给元素,l指向它,l即所得。反之,++l,l也即所得。
  • 所以:循环条件带=号,返回的是l,如果未找到将返回右边界+1的位置。

代码

public class Main {
public static void main(String args[]) {
int[] arr= {2,1,5,3,6,4,8,9,7};
int[] incSec=getLongestIncSeq(arr);
for(int num:incSec) {
System.out.println(num);
}
} public static int[] getLongestIncSeq(int[] arr) {
if(arr==null||arr.length==0) {
return null;
} int[] dp=getDp(arr);
return getIncSeq(dp,arr);
} //得到dp数组
public static int[] getDp(int[] arr) {
int[] dp=new int[arr.length];
dp[0]=1; int[] ends=new int[arr.length];
ends[0]=arr[0];
int end=0;
for(int i=0;i<arr.length;++i) {//遍历arr
int pos=firstBigger(arr[i],ends,end);//遍历ends
if(pos!=end+1) {//找到比arr[i]大的上升子序列结尾元素
//更新dp和ends
dp[i]=pos+1;//长度+1
ends[pos]=Math.min(ends[pos], arr[i]);
}
else {//未找到比arr[i]大的上升子序列结尾元素
//更新dp和ends
dp[i]=end+1+1;//原长度+1
++end;
ends[end]=arr[i];
}
}
return dp;
} //二分查找第一个比num小的元素
public static int firstBigger(int num,int[] ends,int end) {//二分查找第一个比num小的元素
int l=0;
int r=end;
while(l<=r) {//**
int mid=(l+r)/2;//
if(ends[mid]>=num) {
r=mid-1;//
}
else {
l=mid+1;//
}
}
return l;//**
} //输出最长递增子序列
public static int[] getIncSeq(int[] dp,int[] arr) {
int len=Integer.MIN_VALUE;//代表新数组长度 ,并表示新数组索引
int pos=-1;
for(int i=0;i<dp.length;++i) {
len=len>dp[i]?len:dp[i];
pos=len>dp[i]?pos:i;//dp索引,arr索引
} int[] incSeq=new int[len];
incSeq[--len]=arr[pos]; for(int j=pos;j>=0;--j) {
if(dp[j]==len&&arr[j]<arr[pos]) {
incSeq[--len]=arr[j];
pos=j;
}
}
return incSeq;
}
}

[程序员代码面试指南]最长递增子序列(二分,DP)的更多相关文章

  1. [程序员代码面试指南]字符串问题-字符串匹配问题(DP)

    问题描述 字符串str,模式串exp. 必须保证str中无'.'和'星号'字符,并且exp中'星号'不出现在首位,且无连续两个'星号'.PS星号是字符只是暂时没找到markdown的星号转义字符. ' ...

  2. 程序员代码面试指南 IT名企算法与数据结构题目最优解

    原文链接 这是一本程序员面试宝典!书中对IT名企代码面试各类题目的最优解进行了总结,并提供了相关代码实现.针对当前程序员面试缺乏权威题目汇总这一痛点,本书选取将近200道真实出现过的经典代码面试题,帮 ...

  3. 程序员代码面试指南:IT名企算法与数据结构题目最优解

      第1章栈和队列 1设计一个有getMin功能的栈(士★☆☆☆) 1由两个栈组成的队列(尉★★☆☆) 5如何仅用递归函数和栈操作逆序一个栈(尉★★☆☆) 8猫狗队列(士★☆☆☆)10用一个栈实现另一 ...

  4. [程序员代码面试指南]递归和动态规划-最长公共子串问题(DP,LCST)

    问题描述 如题. 例:输入两个字符串 str1="1AB234",str2="1234EF" ,应输出最长公共子串"234". 解题思路 状 ...

  5. [程序员代码面试指南]递归和动态规划-最小编辑代价(DP)

    问题描述 输入 原字符串StrOrg,目标字符串StrTarget,插入.删除.替换的编辑代价ic,dc,rc.输出将原字符串编辑成目标字符串的最小代价. 解题思路 状态表示 dp[i][j]表示把s ...

  6. [程序员代码面试指南]第9章-在两个长度相等的排序数组中找到第k小的数(二分)

    题目 给定两个有序数组arr1和arr2,再给定一个整数k,返回所有的数中第k小的数. 题解 利用题目"在两个长度相等的排序数组中找到第上中位数"的函数 分类讨论 k < 1 ...

  7. [程序员代码面试指南]数组和矩阵问题-找到无序数组中最小的k个数(堆排序)

    题目链接 https://www.nowcoder.com/practice/6a296eb82cf844ca8539b57c23e6e9bf?tpId=13&tqId=11182&t ...

  8. 《程序员代码面试指南》第一章 栈和队列 最大值减去最小值小于或等于num的数量

    题目 给定整数数组arr和整数num,共返回多少的数组满足如下情况 max(arr[i...j]) - min(arr[i...j]) <= num max(arr[i...j])表示数组arr ...

  9. 《程序员代码面试指南》第一章 栈和队列 构造数组的MaxTree

    题目 给出一个无重复元素的数组,构造此数组的MaxTree, java代码 /** * @Description: 构造数组的MaxTree * @Author: lizhouwei * @Creat ...

随机推荐

  1. 使用动态链接为什么还需要静态库lib文件

    在Windows上使用动态链接时,不光需要头文件 .dll文件 还需要一个.lib 文件. 不是动态链接吗?为什么还需要静态库.lib文件? 实际上,这个.lib文件并不是静态库,而是 导入库 文件, ...

  2. 理解正向代理&反向代理

    通常的代理服务器,只用于代理内部网络对Internet的连接请求,客户机必须指定代理服务器,并将本来要直接发送到Web服务器上的http请求发送到代理服务器中.由于外部网络上的主机并不会配置并使用这个 ...

  3. oracle 将数据库的表复制到另一个数据库表内

    将数据库A中的表sys_role复制到数据库B中在数据库b中的SQL工作表写如下代码: 第一步:建立链接 CREATE database link A //数据库名称CONNECT to text  ...

  4. Adaptive Critics and the Basal Ganglia

    郑重声明:原文参见标题,如有侵权,请联系作者,将会撤销发布! This Article is brought to you for free and open access by the Comput ...

  5. IDEA报错:Class JavaLaunchHelper is implemented in both

    在IDEA运行一个程序时报错: Class JavaLaunchHelper is implemented in both 这个错误是Mac下Java 的一个bug,意思是这个JavaLaunchHe ...

  6. (数据科学学习手札94)QGIS+Conda+jupyter玩转Python GIS

    本文完整代码及数据已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 QGIS随着近些年的发展,得益于其开源免费 ...

  7. Mac包管理神器:Home-brew

    最近看到一个大神修改的Homebrew国内脚本,安装非常方便,以前使用国外的经常下载不下来,这个感觉是非常快的. Homebrew 国内自动安装脚本 ,修改原脚本中的 clone 操作为“浅拷贝”(- ...

  8. 基于Nodejs的sequelize操纵数据库

    ## 使用基于ORM架构的sequelize操纵数据库 ### 1.技术背景 ```Sequelize是一个基于promise的关系型数据库ORM框架,*********************技术文 ...

  9. Python淘宝商品比价定向爬虫

    1.项目基本信息 目标: 获取淘宝搜索页面的信息,提取其中的商品名称和价格理解: 淘宝的搜索接口.翻页的处理 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道 ...

  10. Unity NGUI C#性能优化

    建议读者先看这篇博文:http://blog.csdn.net/zzxiang1985/article/details/43339273,有些技术已经变了,比如第1招,unity5的打包机制已经变许多 ...