Java 最长递增子序列_最长递增子序列问题 Java

Java 最长递增子序列_最长递增子序列问题 Java最长递增子序列问题LIS(longestincreasingsubsequence)例如给定一个数列,长度为N,求这个数列的最长上升(递增)子数列(LIS)的长度.以1,7,2,8,3,4为例。这个数列的最长递增子数列是1234,长度为4;次长的长度为3,包括178;123等.设数组为:arr设foo(k)为:以数列中第k项(为了与java数组逻辑…

大家好,又见面了,我是你们的朋友全栈君。

最长递增子序列问题 LIS(longest increasing subsequence) 例如

给定一个数列,长度为N,

求这个数列的最长上升(递增)子数列(LIS)的长度.

以

1, 7, 2, 8, 3, 4

为例。

这个数列的最长递增子数列是 1 2 3 4,长度为4;

次长的长度为3, 包括 1 7 8; 1 2 3 等.

设数组为:arr

设 foo(k) 为:以数列中第k项 (为了与java数组逻辑一致,这里的k从0开始计算) 结尾的最长递增子序列的长度

则:

foo(0) == 1

foo(k) == max(arr[k]>arr[0]?foo(0)+1:foo(0),

arr[k]>arr[1]?foo(1)+1:foo(1) ,

… ,

arr[k]>arr[k-1]?foo(k-1)+1:foo(k-1))

java代码

public class LISDemo {

public static void main(String[] args){

int[] arr = new int[10];

Random random = new Random();

for (int i = 0; i < arr.length; i++) {

arr[i] = random.nextInt(100);

}

System.out.println(“数组”+Arrays.toString(arr));

long time = System.currentTimeMillis();

System.out.println(“结果: “+foo(arr, arr.length-1));

System.out.println(“耗时: “+(System.currentTimeMillis()-time));

}

private static int foo(int[] arr,int end){

if (end==0) {

return 1;

}

int len = 0;

for (int i = 0; i < end; i++) {

int temp = foo(arr,i);

len = Math.max(len,arr[end]>arr[i]?temp+1:temp);

}

return len;

}

}

这段代码能计算出正确的结果,但是存在问题:

要计算 foo(n)必须先得到 foo(0)~foo(n-1)的值

要计算 foo(n-1)必须先得到 foo(0)~foo(n-2)的值

…

以此类推,可以把他画成一颗多叉树,时间复杂度达到O(2^n)

运行这段代码就会发现 每当数组长度+1 运行耗时大致翻倍,数组长度为几十的时候,运行时间已经无法容忍的长了。

以foo(3)为例,可以画成下面这棵树

f89dbd0539d4

可以发现,相同参数的方法被重复计算了多遍,我们可以建立一个hashmap把参数和对应的值存入其中,当结果已经计算过,就直接从hashmap中取出结果不再计算,修改代码为如下,保留了原来的方法做个对比,执行效率天差地别:

public class LISDemo {

public static void main(String[] args){

int[] arr = new int[31];

Random random = new Random();

for (int i = 0; i < arr.length; i++) {

arr[i] = random.nextInt(100);

}

System.out.println(“数组”+Arrays.toString(arr));

LIS lis = new LIS(arr);

long time = System.currentTimeMillis();

System.out.println(“结果1: “+lis.foo());

System.out.println(“耗时1: “+(System.currentTimeMillis()-time));

time = System.currentTimeMillis();

System.out.println(“结果2: “+foo(arr, arr.length-1));

System.out.println(“耗时2: “+(System.currentTimeMillis()-time));

}

// 最长递增子序列 longest increasing subsequence

private static class LIS{

int[] arr;

HashMap values = new HashMap<>();

LIS(int[]arr){

this.arr = arr;

}

int foo(){

return foo(arr,arr.length-1);

}

private int foo(int[] arr,int end){

Integer value = values.get(end);

if (value != null) {

return value;

}

if (end==0) {

values.put(0,1);

return 1;

}

int len = 0;

for (int i = 0; i < end; i++) {

int temp = foo(arr,i);

len = Math.max(len,arr[end]>arr[i]?temp+1:temp);

}

values.put(end,len);

return len;

}

}

private static int foo(int[] arr,int end){

if (end==0) {

return 1;

}

int len = 0;

for (int i = 0; i < end; i++) {

int temp = foo(arr,i);

len = Math.max(len,arr[end]>arr[i]?temp+1:temp);

}

return len;

}

}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/132492.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 遭遇mysql数据库表满错误

    遭遇mysql数据库表满错误

    2021年8月20日
  • 360奇安信天擎卸载不干净_奇安信Ateam

    360奇安信天擎卸载不干净_奇安信Ateam360天擎是什么具体可以参考:百度:360天擎总之,一些单位里为了安全防护,会在单位的电脑上安装360天擎,如果你想用自己的笔记本电脑连上单位的网络的话,也会要求你安装。不安装就连不上网络,但安装之后,卸载又是一个很大的难题。用什么卸载其实网上会有很多强力卸载软件,甚至有些会强力到可以卸载系统文件,这类软件不建议使用(如果用的明白,请自便)。无效方式如,腾讯管家自带的软件管理有效方式如,联想电脑管家,和微软自带的卸载,如下图:点击右键->卸载->完成?不不不,这

    2022年9月25日
  • PLC基础知识(PLC入门必看)[通俗易懂]

    PLC基础知识(PLC入门必看)[通俗易懂]1 PLC的发展历程在工业生产过程中,大量的开关量顺序控制,它按照逻辑条件进行顺序动作,并按照逻辑关系进行连锁保护动作的控制,及大量离散量的数据采集。传统上,这些功能是通过气动或电气控制系统来实现的。1968年美国GM(通用汽车)公司提出取代继电气控制装置的要求,第二年,美国数字公司研制出了基于集成电路和电子技术的控制装置,首次采用程序化的手段应用于电气控制,这就是第一代可编程序控制器,称ProgrammableController(PC)。个人计算机(简称PC)发展起来后,为了方便,也为了反映可

    2022年9月3日
  • 独立成分分析(Independent Components Analysis)「建议收藏」

    独立成分分析(Independent Components Analysis)「建议收藏」首先我们对ICA算法做一些形式化的描述:ICA是用来分离混合源的技术。所以我们准备先混合,再分离,我们定义两个独立的源,上面的称为A,下面的称为B,代码如下: 1然后我们将其线性混合,上面的为A-2*B下面的为1.73*A+3.41*B2之后使用fastica函数,就将两个源分开了:3完整的工程在这里下载:http://research.ics.aalto.fi

    2022年5月16日
  • 画二元函数图像_二元函数怎么画图

    画二元函数图像_二元函数怎么画图目录概述字符串表达式解析图像绘制函数作为属性赋值参考以及说明概述本篇博客主要是在上一篇《每个人都该懂点函数式编程》的基础上,进一步说明“函数”在函数式编程中的重要作用。强调了函数和普通类型一样,可以赋

    2022年8月6日
  • 如何入门网络安全_网络安全自学

    如何入门网络安全_网络安全自学由于我之前写了不少网络安全技术相关的故事文章,不少读者朋友知道我是从事网络安全相关的工作,于是经常有人在微信里问我:我刚入门网络安全,该怎么学?要学哪些东西?有哪些方向?怎么选?不同于Java、C/C++等后端开发岗位有非常明晰的学习路线,网路安全更多是靠自己摸索,要学的东西又杂又多,难成体系。常读我文章的朋友知道,我的文章基本以故事为载体的技术输出为主,很少去谈到职场、面试这些方面的内容。主要是考虑到现在大家的压力已经很大,节奏很快,公众号上是让大家放松的地方,尽量写一些轻快的内容。不

    2022年10月21日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号