经典DP-最长单调子序列

news/2024/6/1 23:05:02 标签: 动态规划, 算法, java, 开发语言, leetcode

最长递增子序列

思路

  1. 定义状态
    • 我们定义一个数组 dp,其中 dp[i] 表示以 nums[i] 结尾的最长递增子序列的长度。
  2. 初始化状态
    • 对于数组中的每个元素 nums[i],初始时都可以被视为一个长度为1的递增子序列,因此 dp[i] 的初始值都设为1。
  3. 状态转移方程
    • 对于数组中的每个位置 i,我们遍历它之前的所有位置 jj < i)。
    • 如果 nums[i] 大于 nums[j],说明 nums[i] 可以接在以 nums[j] 结尾的递增子序列后面,形成一个更长的递增子序列。
    • 在这种情况下,我们可以更新 dp[i] 为 dp[j] + 1,表示以 nums[i] 结尾的递增子序列长度是以 nums[j] 结尾的子序列长度加1。
    • 我们需要遍历所有 j < i 的情况,并取 dp[j] + 1 中的最大值来更新 dp[i]
  4. 求解结果
    • 在完成所有状态转移后,dp 数组中的最大值就是最长递增子序列的长度。
    • 因为 dp[i] 存储的是以 nums[i] 结尾的最长递增子序列的长度,所以最长递增子序列的实际长度可能不在数组末尾,而是在数组中的某个位置。
    • 因此,我们需要遍历整个 dp 数组来找到最大值,这个最大值就是最长递增子序列的长度。
  5. 优化空间复杂度
    • 上述方法的空间复杂度是 O(n),因为我们需要一个大小为 n 的 dp 数组来存储状态。
    • 但实际上,我们只需要知道前一个状态 dp[j] 的值来更新当前状态 dp[i],因此可以使用一个变量来替代整个数组,从而将空间复杂度优化到 O(1)。
  6. 实现细节
    • 在实际编码时,我们需要处理边界情况,比如输入数组为空或只有一个元素的情况。
    • 在 main 方法中,我们需要创建 LongestIncreasingSubsequence 类的实例,并调用其 lengthOfLIS 方法来获取结果。

代码

java">
import java.util.Scanner;
//给你一个整数数组nums,
//找到其中最长严格递增子序列的长度
public class 最长递增子序列 {
	
//写一个方法
	public int lengthOfLIS(int [] nums) {
		//在方法的开始,我们首先处理边界情况
		if(nums==null || nums.length==0) {
			return 0;
		}
		//dp[i]将存储以nums[i]结尾的最长递增子序列的长度。
		int[] dp=new int[nums.length];
		//初始化一个变量maxLength,用于跟踪目前为止找到的最长递增子序列的长度
		int maxLength=1;
		
		for(int i=0;i<nums.length;i++) {
			dp[i]=1;//将dp[i]初始化为1,因为任何元素都可以作为一个长度为1的递增子序列。
			for(int j=0;j<i;j++) {//再用一个内层for循环遍历当前元素之前的所有元素。
				//在内层循环中,我们检查当前元素nums[i]是否大于前面的元素nums[j]
				if(nums[i]>nums[j]) {
					dp[i] = Math.max(dp[i], dp[j]+1);
				}
			}
			maxLength=Math.max(maxLength, dp[i]);
		}
		return maxLength;
	}
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		最长递增子序列 ss =new 最长递增子序列();
		int [] nums= {10,9,2,5,3,7,101,18};
		int result = ss.lengthOfLIS(nums);
	     System.out.println(result);  
	}
}

最长递增子序列的个数

代码

java">import java.util.Arrays;

public class 最长递增子序列的个数 {
	public int findNumberOfLIS(int[] nums) {
		if(nums==null || nums.length==0) {
			return 0;
		}
		int n=nums.length;
		int[] dp=new int[n];//dp[i] 存储以 nums[i] 结尾的最长递增子序列的长度
		int[] count = new int[n];//count[i] 存储以 nums[i] 结尾的最长递增子序列的个数
		Arrays.fill(count, 1);//初始化count数组,每个元素的最长递增子序列至少包含一个元素
		
		int maxLength = 1;//最长递增子序列的长度
		
		for(int i=0;i<n;i++) {
			dp[i]=1;
			for(int j=0;j<i;j++) {
				if(nums[i]>nums[j]) {
					if(dp[j]+1>dp[i]) {
						//如果发现一个更长的递增子序列,更新 dp[i] 并重置 count[i]  
						dp[i]=dp[j]+1;
						count[i]=count[j];
					}
					else if(dp[j]+1==dp[i]){
						count[i] += count[j];
					}
				}
			}
			maxLength = Math.max(maxLength, dp[i]);
		}
		int result=0;
		for(int i=0;i<n;i++) {
			if(dp[i]==maxLength) {
				result+=count[i];
			}
		}
		return result;
	}
	public static void main(String[] args) {
		最长递增子序列的个数 solution=new 最长递增子序列的个数();
		int [] nums= {1,3,5,4,7};
		int count=solution.findNumberOfLIS(nums);
		System.out.println(count);
	}

}

知识点

Arrays.fill(count, 1);

 是 Java 中的一个方法调用,用于将数组 count 的所有元素设置为指定的值,即 1。这个方法来自于 java.util.Arrays 类,是一个静态工具类,提供了很多用于操作数组(例如排序、搜索、填充等)的静态方法。

在这个特定的情境下,Arrays.fill(count, 1); 被用来初始化 count 数组。由于我们正在计算最长递增子序列的个数,每个元素至少可以作为一个长度为 1 的递增子序列的结束元素。因此,count 数组的每一个位置都被设置为 1,意味着每个元素开始时都被视为一个独立的递增子序列。


http://www.niftyadmin.cn/n/5398318.html

相关文章

【0271】postgres内核共享数组(procArray)移除指定MyProc(PGPROC)

相关文章: 【0267】pg内核初始化 process table(ProcGlobal、PROC_HDR、PGPROC)分析 【0268】深入分析PG内核 shared PGPROC array(ProcArrayStruct、procArray)初始化机制 【0269】揭晓pg内核procArray、MyProc、ProcGlobal三者间的微妙关系 【0270】揭晓postgres内核pr…

安卓开发1- android stdio环境搭建

安卓开发1-android stdio环境搭建 Jdk环境搭建 1. 准备Jdk,这边已经准备好了jdk1.8.0,该文件直接使用即可 2. 系统变量添加 %JAVA_HOME%\bin JAVA_HOME 3. 系统变量&#xff0c;Path路径添加 4. 添加完成后&#xff0c;输入命令javac / java -version&#xff0c;验证环…

PHP堆栈+errLog定位

调用堆栈&#xff08;Call Stack&#xff09;是一个记录了程序在运行时所有活动子例程的栈结构。它以函数调用的方式描述了程序的执行流程和调用关系。 在PHP中&#xff0c;我们可以通过打印PHP调用堆栈来辅助调试和定位代码中的问题。本文将介绍如何在PHP中打印调用堆栈&…

Linux 系统上查看系统的相关信息

在 Linux 系统上查看系统的相关信息&#xff0c;可以使用一些命令来获取有关硬件、网络、系统状态等方面的信息。以下是一些常用的命令&#xff1a; 1. 查看系统信息&#xff1a; 使用 uname 命令查看内核信息&#xff1a; uname -a使用 lsb_release 命令查看 Linux 发行版信息…

力扣区间题:合并区间、插入区间

我们可以将区间按照左端点升序排列&#xff0c;然后遍历区间进行合并操作。 我们先将第一个区间加入答案&#xff0c;然后依次考虑之后的每个区间&#xff1a; 如果答案数组中最后一个区间的右端点小于当前考虑区间的左端点&#xff0c;说明两个区间不会重合&#xff0c;因此…

1399. 统计最大组的数目

说在前面 &#x1f388;不知道大家对于算法的学习是一个怎样的心态呢&#xff1f;为了面试还是因为兴趣&#xff1f;不管是出于什么原因&#xff0c;算法学习需要持续保持。 题目描述 给你一个整数 n 。请你先求出从 1 到 n 的每个整数 10 进制表示下的数位和&#xff08;每一…

Linux使用Docker部署Nacos容器并结合内网穿透实现公网访问本地服务

文章目录 推荐1. Docker 运行Nacos2. 本地访问Nacos3. Linux安装Cpolar4. 配置Nacos UI界面公网地址5. 远程访问 Nacos UI界面6. 固定Nacos UI界面公网地址7. 固定地址访问Plik 推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff…

第六章 使用或更换专用 Web 服务器 - 使用不同的 Web 服务器运行管理门户

文章目录 第六章 使用或更换专用 Web 服务器 - 使用不同的 Web 服务器运行管理门户使用不同的 Web 服务器运行管理门户管理私有 Web 服务器进行配置更改 管理 Windows 上的专用 Web 服务器管理 UNIX 上的专用 Web 服务器 第六章 使用或更换专用 Web 服务器 - 使用不同的 Web 服…