最长递增子序列(LIS)

最长递增子序列(LIS)的三种算法 最长递增子序列:给定一个长度为N的数组,找出一个最长的单调递增子序列,子序列不一定连续,但初始顺序不能乱。 比如数组A={1,3,4,2,5},其最长递增子序列为1,3,4,5 方法一:最长公共子序列法 对于给定长度为N的数组A: 使数组B为排序后的数组A (O(NlogN)) 求出A与B的最长公共子序列(LCS) (O(N2)) 对求得的公共子序列进行去重 (O(N)... 阅读详情

最长递增子序列(Longest Increasing Subsequence) ,我们简记为 LIS。

题:求一个一维数组arr[i]中的最长递增子序列的长度,如在序列1,-1,2,-3,4,-5,6,-7中,最长递增子序列长度为4,序列为1,2,4,6。

 解法一:快速排序+LCS

        刚开始做这道题的时候,由于之前做过几道LCS的题,于是最先想到的是快速排序+LCS的方法。这种方法解决了当时只计算单个case的问题,但是后来面对计算多个    case的问题的时候,第一次遇到Memory Limit Exceeded。于是就意识到这种简单解法的时间和空间的复杂度都太高了。于是只能另寻他法。

public class Main {
	static  int n;
	static int[] a;
	static int[] b;
	static int[][] z;
	public static void QuickSort(int[] a){
		QSort(a,1,n);
	}
	public static void QSort(int[] a,int p,int r){
		if(p<r)
		{
			int q=Partition(a,p,r);
			QSort(a,p,q-1);
			QSort(a,q+1,r);
		}
	}
	
	public static int  Partition(int[] a,int p,int r){
		int x=a[r];
		int i=p-1;
		for(int j=p;j<r;j++)
		{
			if(a[j]<=x){
				i=i+1;
				swap(a, i, j);
			}
		}
		swap(a, i+1, r);
		return i+1;
	}
	public static void swap(int[] a, int i,int j){
    	int temp;
    	temp=a[j];
    	a[j]=a[i];
    	a[i]=temp;
    }
	public static int LCS(int a[],int[] b){    
        z=new int [n+1][n+1];    
        int i,j;    
        for( i=0;i<=n;i++)    
            z[i][0]=0;    
        for( j=0;j<=n;j++)    
            z[0][j]=0;    
            
        for(i=1;i<=n;i++){    
            for( j=1;j<=n;j++){    
                if(a[i]==b[j]){    
                    z[i][j]= z[i-1][j-1]+1;    
                }    
                else    
                    z[i][j]=z[i-1][j] > z[i][j-1] ?z[i-1][j]:z[i][j-1];    
            }    
        }    
        return z[n][n];    
    }    
    public static void main(String[] args) {  
    	int arr[] = {1,-1,2,-3,4,-5,6,-7};
	    n=arr.length;
        a=new int[n+1];
        b=new int[n+1];
	    int i,j;
        for(i=1;i<=n;i++){
        	b[i]=a[i];
        }
	    QuickSort(a);
	    //控制严格递增
        for(i=1;i<n;i++){
        	for(j=i+1;j<=n;j++){
	        	if(a[i]!=-1 && a[i]==a[j])
	        		a[j]=-1;
        	}
        }
	        System.out.println(LCS(a,b));
        }
} 


解法二:DP(O(N^2))

        从后向前分析,很容易想到,第i个元素之前的最长递增子序列的长度要么是1(单独成一个序列),要么就是第i-1个元素之前的最长递增子序列加1,可以有状态方程:

       LIS[i+1] = max{1,LIS[k]+1},aray[k],for any k <=i.

       即如果array[i+1]大于array[k],那么第i+1个元素可以接在LIS[k]长的子序列后面构成一个更长的子序列。于此同时array[i+1]本身至少可以构成一个长度为1的子序列。

public int LIS(int[] arr, int size){

 
int dp[40]; /* dp[i]记录到[0,i]数组的LIS */
int lis;    /* LIS 长度 */
 for(int i = 0; i < size; ++i){ dp[i] = 1; for(int j = 0; j < i; ++j){ if(arr[i] > arr[j] && dp[i] < dp[j] + 1){ dp[i] = dp[j] + 1; if(dp[i] > lis){ lis = dp[i]; } } } } return lis; }
解法三:二分查找+DP(O(nlogn))

       在解法二中,当考察第i+1个元素的时候,我们是不考虑前面i个元素的分布情况的。现在我们从另一个角度分析,即当考察第i+1个元素的时候考虑前面i个元素的情况。
      目的:我们期望在前i个元素中的所有长度为len的递增子序列中找到这样一个序列,它的最大元素比arr[i+1]小,而且长度要尽量的长,如此,我们只需记录len长度的递增子序列中最大元素的最小值就能使得将来的递增子序列尽量地长。

      方法:维护一个数组MaxV[i],记录长度为i的递增子序列中最大元素的最小值,并对于数组中的每个元素考察其是哪个子序列的最大元素,二分更新MaxV数组,最终i的值便是最长递增子序列的长度。

       仔细的分析请看最长递增子序列 O(NlogN)算法,

public class LIS {
	/* 最长递增子序列 LIS
	 * 设数组长度不超过 30
	 * DP + BinarySearch
	*/
	static int[] MaxV=new int[30];   /* 存储长度i+1(len)的子序列最大元素的最小值 */
	static int len;                  /* 存储子序列的最大长度 即MaxV当前的下标*/
	static int BinSearch(int[] MaxV, int size, int x){ /* 返回MaxV[i]中刚刚不小于x的那个元素的下标 */
	    int left = 0, right = size-1;
	    while(left <= right){
	        int mid = (left + right) / 2;
	        if(MaxV[mid] <= x){
	            left = mid + 1;
	        }else{
	            right = mid - 1;
	        }
	    }
	    return left;
	}
	 
	static int getLIS(int[] arr, int size){
	    MaxV[0] = arr[0]; /* 初始化 */
	    len = 1;
	    for(int i = 1; i < size; ++i){ /* 寻找arr[i]属于哪个长度LIS的最大元素 */
	    	
	        if(arr[i] > MaxV[len-1]){ /* 大于最大的自然无需查找,否则二分查其位置 */
	        
	            MaxV[len++] = arr[i];
	        }else{
	            int pos = BinSearch(MaxV,len,arr[i]);
	            MaxV[pos] = arr[i];
	        }
	    }
	    return len;
	}
	 
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int arr[] = {1,-1,2,-3,4,-5,6,-7};
	    /* 计算LIS长度 */
	    System.out.println(getLIS(arr,arr.length));
	}
}

参考资料:

《编程之美》 2.16

  Felix’s Blog:最长递增子序列 O(NlogN)算法

  勇幸|Thinking (http://www.ahathinking.com) 






Visio 2013 Professional密钥安装激活全攻略:版本匹配与故障排查 产品密钥是软件授权体系中的核心凭证,用于验证用户对软件的使用权限。在微软Office产品线中,Visio 2013 Professional采用25位字符的密钥机制,通过联网或电话方式完成激活。正确使用密钥不仅能确保软件功能完整,还能避免因授权问题导致的工作中断。对于企业IT运维和个人用户而言,掌握密钥类型辨析、安装包匹配规则以及激活失败排查方法,是保障老版本软件稳定运行的关键。本文围绕Visio 2013 Professional,详细讲解密钥输入、激活流程及常见错误代码处理,帮助读者高效完成部署与维护。 阅读详情

相关推荐

如何加载交易策略EA到MT4/MT5

1、打开MT4/MT5软件 2、首先,必须有一个EA,而且必须是mq4/ex4为扩展名。点击左上角“文件”—“打开数据文件夹”,找到安装路径 3、将EA的ex4或mq4文件放到MT4目录\MQL4\Experts里面(本文以名为Demo的EA为例) 4、如果有DLL库文件,复制到experts目录下的libraries子目录中 5、如果有tpl模板文件,复制到templates目录中 6、添加完成后重启MT4,点击允许EA运行图标 7、在导航中找到刚才安装的EA,拖拽到...

weixin_41364817的博客 7359

最长递增子序列

问题 给定一个长度为N的数组,找出一个最长的单调自增子序列(不一定连续,但是顺序不能乱)。例如:给定一个长度为6的数组A{5, 6, 7, 1, 2, 8},则其最长的单调递增子序列为{5,6,7,8},长度为4. 解法1:最长公共子序列法 这个问题可以转换为最长公共子序列问题。如例子中的数组A{5,6, 7, 1, 2, 8},则我们排序该数组得到数组A‘{1, 2, 5, 6, 7,...

切梦 5417

Python经常遇到导入xlwings就出错,如何解决

Python经常在导入xlwings时遇到错误。有人建议尝试重装或升级xlwings,但这些操作后仍然无法解决导入错误问题。

felix_8的博客 1739

算法学习20—LIS 最长递增子序列

假设你是球队的经理。对于即将到来的锦标赛,你想组合一支总体得分最高的球队。球队的得分是球队中所有球员的分数。是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。dfs(i) 表示以 nums[i] 结尾的 LIS 的长度。一名年龄较大的球员,则存在矛盾。同龄球员之间不会发生矛盾。把 dfs 改成 f 数组,递归改成循环,就完事了。然而,球队中的矛盾会限制球员的发挥,所以必须选出一支。,找到其中最长严格递增子序列的长度。如果一名年龄较小球员的分数。名球员的分数和年龄。

weixin_45699456的博客 194

RC电路(一):微分|积分

的取值不同,会导致输出波形和输入波形之间的关系也不同,由此也会产生不同的应用。输出为0,随着电容充满电,运放-输入端得到的分压为正最大值,可等效成一个电压源,且电压不可突变,此时电流反向为最大值,开始充电时的容抗为0,电压不可突变则电压差为0,运放。开始充电时的容抗为0,电压不可突变则电压差为0,运放。输入端得到的分压也不可突变,随着电容放完电,于是。,因电容上电压不能突变(来不及充电,相当于短路,由上分析可得积分运算电路中,输出为运放的负最大峰值,随着电容充满电,输出为运放的正最大峰值,随着电容放完电,

既有随处可栖的江湖,也有追风逐梦的骁勇! 1万+

【32】C# WinForm入门到精通 ——打开文件OpenFileDialog 【属性、方法、事件、实例、源码】

本文介绍了WinForm开发中OpenFileDialog控件的关键属性及其应用。OpenFileDialog是.NET Framework提供的文件对话框控件,主要用于选择、打开文件操作。文章详细讲解了11个核心属性:AddExtension(自动补全扩展名)、AutoUpgradeEnabled(外观升级)、CheckFileExists/CheckPathExists(文件/路径存在验证)、DefaultExt(默认扩展名)、DereferenceLinks(解析快捷方式)、FileName/File

程序员,他们想的是什么?他们想的永远都是技术,他们崇尚的也永远都是技术。 1534

动态规划算法之最长递增子序列详细解读(附带Java代码解读)

最长递增子序列(Longest Increasing Subsequence, LIS)问题是动态规划中的一个经典问题,目标是在给定序列中找到一个最长的子序列,该子序列中的元素是严格递增的。

欢迎来到我的博客!这里是一个专注于计算机技术的分享平台,涵盖编程开发、算法研究、系统架构、软件工程等多个领域。无论你是初学者还是资深开发者,都能在这里找到有价值的内容。 2975

【文献笔记】CVPR 2023|Attention-Based Point Cloud Edge Sampling

优点能够有效采出点云数据的边缘点分类任务性能优越不足没有设计出一个更好的上采样方法,导致分割任务的性能略低只考虑了边缘特征,没有利用其他几何特征。

m0_55908255的博客 318

最长递增子序列(LIS)+最长公共子序列(LCS)+最长公共递增子序列(LICS)

最长递增子序列(LIS)问题是一个经典的动态规划问题,其目标是找到给定序列中的最长递增子序列的长度。递增子序列是指序列中的元素按照顺序排列,并且每个元素都大于前面的元素。让我们通过一个具体的例子来说明最长递增子序列(LIS)问题的解法。假设我们有一个序列:3,4,1,5,7,2,6我们的目标是找到这个序列的最长递增子序列。我们首先初始化这个数组为1,1,1,1,1,1,1,因为每个元素本身都可以作为一个长度为1的递增子序列。

benedict_q的博客 1689

C#实战:从零搭建Vosk离线语音转文字系统

本文手把手教你用C#构建离线语音转文字系统,基于NAudio和Vosk实现全流程开发。首先介绍环境搭建,包括NuGet包安装和中文模型配置,强调16kHz单声道音频格式的关键性。接着详细解析音频预处理转换、Vosk模型初始化及识别过程的核心代码,提供多线程优化建议和实时识别扩展思路。文章包含80%以上代码注释,从常见问题排查到性能优化技巧,完整覆盖从"Hello World"到工业级部署的关键技术点,特别适合需要开发本地化语音识别应用的C#开发者。

墨夶的博客 752

机器人中的数值优化(十三)——QP二次规划

本系列文章主要是我在学习《数值优化》过程中的一些笔记和相关思考,主要的学习资料是深蓝学院的课程《机器人中的数值优化》和高立编著的《数值最优化方法》等,本系列文章篇数较多,不定期更新,上半部分介绍无约束优化,下半部分介绍带约束的优化,中间会穿插一些路径规划方面的应用实例

慕羽★的博客 2792

最长递增子序列(LIS)问题详解

最长递增子序列(Longest Increasing Subsequence,简称LIS)是动态规划领域的经典问题,它看似简单——在一个无序数组中找到最长的严格递增子序列(子序列无需连续),但背后隐藏着从暴力到高效的多种解法思路。本文我将系统解析LIS问题的核心逻辑,从基础的动态规划到优化的“二分查找+贪心”解法,并结合代码实现、复杂度分析及变种拓展全面解读。

1815

华为OD机试真题 新系统2026-04-01 Java&Go 实现【勇攀数字高峰】

请你在给定的数字地形图中寻找登山路径,数字代表当前位置的海拔高度,要求从最低海拔出发,不断攀登,最终到达最高山峰。你需要寻找所有满足条件的登山路径。地图已经保证最低海拔和最高山峰都只有一个。

MISAYAONE的博客 610

LIS 最长递增子序列

前言 LIS 即 longest increasing string,最长递增子序列,可以是不连续的。例如 2 3 5 2 3 4 5 的最长递增子序列为{2,3,4,5},长度为4. 两种方法可以求出,一种O(n^2)的动态规划算法,一种是O(nlogn)的二分查找算法。 动态规划算法 具体思路 : 设置一个dp[i],代表以a[i]为末位的最长递增子序列的长度。其状态转换方程为 dp[i] ...

彤云望月 359

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

动态规划求解最长递增子序列(LIS)

动态规划求解最长递增子序列(LIS)

yishiduoshhaojie的博客 2337

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

算法-最长递增子序列LIS

【题目】给定数组arr,返回arr的最长递增子序列LIS。【思路】设dp[i]表示在以arr[i]这个数结尾的情况下,LIS长度。动态规划思想:最后一个数arr[N-1]的LIS长度:设j属于集合[0, N-1)(1)若arr[N-1] &lt; arr[j],则dp[N-1]==1。含义是arr[N-1]小于前面所有数,最长子递增序列只有自己一个数。(2)若arr[N-1] &gt; arr[j...

少年乖 400

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

动态规划 - 最长递增子序列(LIS)

动态规划 - 最长递增子序列(LIS) 最长递增子序列是动态规划中经典的问题,详细如下: 在一个已知的序列{a1,a2,...,an}中,取出若干数组组成新的序列{ai1,ai2,...,aim},其中下标i1,i2,...,im保持递增,即新数列中的各个数之间依...

dichuangheng8094的博客 951

最长上升( 递增 )子序列与最长连续上升( 递增 )子序列( LIS )

文章目录最长上升( 递增 )子序列与最长连续上升( 递增 )子序列( LIS )1. 最长上升子序列题目描述说明暴力 dp 解法转化为LCS求解二分查找+贪心2.最长连续上升子序列题目描述dp 解法3. 最长递增子序列的个数题目描述dp 解法 最长上升( 递增 )子序列与最长连续上升( 递增 )子序列( LIS ) 1. 最长上升子序列 LintCode题目地址: 76. 最长上升子序列 Leet...

charlsonzhao的博客 2092

最长递增子序列(LIS)问题

最长递增子序列问题的算法最低要求O(nlogn)的时间复杂度

Nim的辙迹 933

最长公共子序列(LCS),最长递增子序列(LIS),最长递增公共子序列(LICS)

最长公共子序列(LCS),最长递增子序列(LIS),最长递增公共子序列(LICS) 最长公共子序列(LCS) 【问题】 求两字符序列的最长公共字符子序列 问题描述:字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列。令给定的字符序列X=“x0,x1,…,xm-1”,序列Y=“y0,y1,…,yk-1”是X的子序列,存在X的一个严格递增下标序...

菜鸡的博客 590

今日算法:LIS算法(最长递增子序列)

本文探讨了导弹拦截问题中的最长单调不递增子序列及其覆盖问题。通过分析发现,该问题可通过Dilworth定理转化为求解最长上升子序列问题。文章详细解释了定理内容:在有限偏序集中,最大反链大小等于最小链覆盖数。作者采用O(nlogn)算法实现,首轮求解最长不递增子序列长度,次轮转化为最长上升子序列。最终代码通过二分查找优化,成功解决了需要同时计算最多拦截导弹数和最少系统配备数的双重要求。

2403_87289238的博客 1087

最长递增子序列(LIS)-总结与相关展开

LIS是典型的DP问题,之前有做到过一些类型的LIS题目,现在把LIS的相关题型做一个总结,也是对思路的一个梳理。 一、最基础的LIS问题: 给出一个序列,只要求输出最长递增子序列的长度,对于这种题目我们可以用两种方法定义dp数组: 1.O(N^2) dp[i]:以ai为末尾的最长上升子序列长度//方法一: //O(N^2) //定义:dp[i]:以ai为末尾的最长上升子序列长度 //dp

EaShion1994的专栏 699

最长递增子序列的三种解法(LIS)

最长递增子序列的三种解法(LIS) 1.用LCS(求LIS) 时间复杂度O(n^2) 思路:将原序列a排序后产生一个新的序列b,比较a和b最长公共子序 结果就是LIS. #include<bits/stdc++.h> using namespace std; const int N=1e4+5; int dp[2][N];//滚动数组优化 string a,b; int LCS(...

Harris-H的博客 793

【串和序列处理 7】LIS 最长递增子序列

LIS: 给定一个字符串序列S={x0,x1,x2,...,x(n-1)},找出其中的最长子序列,而且这个序列必须递增存在。   下面给出解决这个问题的几种方法:   (1) 转化为LCS问题         思想: 将原序列S递增排序成序列T,然后利用动态规划算法取得S与T的公共最长子序列。具体算法详见《LCS最长公共子序列 》。         

Aiphis的博客 348

一个数组求其最长递增子序列(LIS)

一个数组求其最长递增子序列(LIS) 例如数组{3, 1, 4, 2, 3, 9, 4, 6}的LIS是{1, 2, 3, 4, 6},长度为5,假设数组长度为N,求数组的LIS的长度, 需要一个额外的数组LIS 来记录 长度从1 到 n 慢慢变长求解的过程中 对应长度的 最长递增子序列的最小的末尾元素 解决方法 长度为1时 {3}: 将3放入LIS中,表示长...

weixin_30349597的博客 152
上一篇: 广度优先搜索(BFS)
下一篇: Poj 3903 Stock Exchange(LIS)
TaiSung
博客等级 码龄15年 49粉丝 132原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值