最长递增子序列-LeetCode
300. 最长递增子序列-LeetCode
🎯 问题描述(来源于LeetCode)
描述:给你一个整数数组 nums,找到其中最长严格递增子序列的长度。
说明:
-
子序列是由数组元素删除(或不删除)任意数量的元素后,不改变其余元素顺序得到的序列。
-
示例:
- 示例 1:
1
2
3输入:nums = [10,9,2,5,3,7,101,18]
输出:4
解释:最长递增子序列是 [2,3,7,18],长度为 4。- 示例 2:
1
2输入:nums = [0,1,0,3,2,3]
输出:4
💻 解题思路
思路1:动态规划 (自底向上)
核心思想:
这是一个标准的线性 DP 问题。
- 状态定义:
dp[i]表示以nums[i]为结尾的最长递增子序列的长度。- 注意:必须定义为“以 i 结尾”,而不是“前 i 个元素中的最大长度”,这样才能推导状态转移。
- 状态转移:对于每个元素
i,我们去看它前面所有的元素j。- 如果
nums[j] < nums[i],说明i可以接在j后面。 - 此时
dp[i] = max(dp[i], dp[j] + 1)。
- 如果
- 初始化:每个单独的元素本身就是一个长度为 1 的子序列,所以
dp数组全部初始化为 1。
算法步骤:
- 初始化
dp数组,长度为n,值全为 1。 - 外层循环遍历每个位置
i。 - 内层循环遍历
i之前的所有位置j。 - 如果满足递增条件
nums[j] < nums[i],尝试更新dp[i]。 - 最后返回
dp数组中的最大值。
思路1:代码实现
1 | class Solution: |
思路1:📊 性能分析
提交结果
- 运行时间:1379ms击败41.36%
- 内存消耗:19.26MB击败58.75%
复杂度验证
- 时间复杂度:
- 解析:两层嵌套循环,外层N次,内层平均N/2次。
- 空间复杂度:
- 解析:创建了一个长度为N的
dp数组。
- 解析:创建了一个长度为N的
思考
-
为什么返回
max(dp)而不是dp[-1]?- 因为我们定义的
dp[i]是以nums[i]结尾的最长子序列。 - 全局最长子序列可能在数组中间就结束了,不一定非要包含最后一个数字。所以需要遍历整个
dp数组找最大值。
- 因为我们定义的
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 笺札!






