1. 题目
读题
考查点
这道题的考查点是:
- 如何定义合适的状态,即dp[i]的含义。
- 如何找到状态转移方程,即dp[i]和dp[j]的关系。
- 如何初始化和更新状态,即dp[i]的初始值和最大值。
- 如何从状态数组中得到最终结果,即res的值。
2. 解法
思路
讲一下思路吧。
这个问题的核心是找到数组中的最长递增子序列,也就是说,找到一个子序列,使得它的元素从左到右递增,并且长度最大。
我们可以用动态规划的方法来解决这个问题,动态规划的思想是把一个大问题分解成若干个小问题,并且利用已经解决的小问题的结果来解决大问题。
具体来说,我们可以定义一个状态dp[i],表示以nums[i]为结尾的最长递增子序列的长度。也就是说,如果我们知道了dp[i]的值,那么我们就知道了以nums[i]结尾的最长递增子序列是什么。
那么,如何求解dp[i]呢?我们可以从前往后遍历数组,对于每个元素nums[i],我们可以遍历它之前的所有元素nums[j],如果nums[j] < nums[i],那么说明nums[j]和nums[i]可以构成一个递增子序列,而且这个递增子序列的长度就是dp[j] + 1。所以,我们可以用dp[j] + 1来更新dp[i],取最大值。这样,我们就得到了以nums[i]为结尾的最长递增子序列的长度。
最后,我们只需要遍历一遍dp数组,找到其中的最大值,就是整个数组的最长递增子序列的长度了。
这道题的状态转移公式是:
dp[i]=0≤j<i and nums[j]<nums[i]max(dp[j]+1)
也就是说,dp[i]等于在所有满足nums[j] < nums[i]的j中,找到最大的dp[j] + 1。
这个公式的意义是,对于每个元素nums[i],我们要找到它之前的所有比它小的元素nums[j],并且找到这些元素中最长递增子序列的长度dp[j],然后加上1,就是以nums[i]为结尾的最长递增子序列的长度了。
代码逻辑
代码的逻辑如下:
- 首先,创建一个dp数组,dp[i]表示以nums[i]为结尾的最长递增子序列的长度。
- 然后,初始化dp数组,每个元素最小都为1,因为每个元素自己就是一个长度为1的递增子序列。
- 接着,创建一个变量res,用来记录最终的结果,初始值为0。
- 然后,遍历数组,从第二个元素开始,对于每个元素nums[i],我们可以遍历它之前的所有元素nums[j],如果nums[j] < nums[i],那么说明nums[j]和nums[i]可以构成一个递增子序列,而且这个递增子序列的长度就是dp[j] + 1。所以,我们可以用dp[j] + 1来更新dp[i],取最大值。这样,我们就得到了以nums[i]为结尾的最长递增子序列的长度。
- 最后,遍历一遍dp数组,找到其中的最大值,赋给res,就是整个数组的最长递增子序列的长度了。
具体实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | class Solution { public int lengthOfLIS( int [] nums) { // 创建一个dp数组,dp[i]表示以nums[i]为结尾的最长递增子序列的长度 int [] dp = new int [nums.length]; // 初始化dp数组,每个元素最小都为1 for ( int i = 0 ; i < nums.length; i++) { dp[i] = 1 ; } // 创建一个变量res,用来记录最终的结果 int res = 0 ; // 遍历数组,从第二个元素开始 for ( int i = 1 ; i < nums.length; i++) { // 遍历当前元素之前的所有元素 for ( int j = 0 ; j < i; j++) { // 如果当前元素大于之前的元素,说明可以构成递增子序列 if (nums[i] > nums[j]) { // 更新dp[i],取最大值 dp[i] = Math.max(dp[i], dp[j] + 1 ); } } // 更新res,取最大值 res = Math.max(res, dp[i]); } // 返回结果 return res; } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
2019-05-01 java中的12种锁
2019-05-01 公平锁与非公平锁
2019-05-01 设计模式:门面模式(Facade)
2019-05-01 设计模式:装饰者模式
2019-05-01 设计模式:组合模式
2019-05-01 设计模式:桥接模式
2019-05-01 设计模式:适配器模式(Adapter)