力扣HOT100(52)动态规划 - 最长递增子序列

先搞懂:什么是「子序列」?

这是新手最容易搞混的点,一定要和「子串」区分开:

  • 子串 :必须是数组中连续的一段元素
  • 子序列 :可以不连续,但元素的相对顺序不能变

比如数组 [10,9,2,5,3,7,101,18]:

  • 子串:[2,5,3](连续)
  • 子序列:[2,3,18](不连续,但顺序不变)

题目要求

找到数组中最长的严格递增子序列的长度

  • 严格递增:后一个元素必须大于前一个,不能等于
  • 子序列可以不连续,但顺序不能乱

核心思路(一句话讲透)

用 dp[i] 表示:以第 i 个元素结尾的最长递增子序列的长度 。 对于每个元素 nums[i],我们看它前面所有比它小的元素 nums[j](j < i):

  • 如果 nums[j] < nums[i],说明 nums[i] 可以接在 nums[j] 后面,形成一个更长的子序列
  • 这个更长的子序列长度就是 dp[j] + 1
  • 我们在所有可能的 dp[j] + 1 中取最大值,就是 dp[i] 的值

所以状态转移方程:

plaintext

复制代码
dp[i] = max(dp[j] + 1)  (其中 0 ≤ j < i 且 nums[j] < nums[i])

完整解题步骤

  1. 处理边界情况:如果数组为空,直接返回 0
  2. 初始化 dp 数组 :
    • 数组长度为 n(和原数组一样长)
    • 所有元素初始化为1(因为每个元素自己就是一个长度为 1 的子序列)
  3. 遍历计算 dp 数组 :
    • 外层循环:i从0到n-1(当前要计算的元素)
    • 内层循环:j从0到i-1(前面所有的元素)
      • 如果 nums[j] < nums[i](可以接在后面)
      • 更新 dp[i] = max(dp[i], dp[j] + 1)
  4. 返回结果 :dp 数组中的最大值
    • 注意:最长子序列不一定以最后一个元素结尾,所以不能直接返回dp[n-1]
cpp 复制代码
class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        int n = nums.size();
        if(n == 0)
            return 0;


        vector<int> dp(n,1);//初始值设成1 因为序列最短包括自己 长度为1

        for(int i = 0;i<n;i++){
            for(int j = 0;j<i;j++){
                if(nums[j]<nums[i]){
                    dp[i] = max(dp[i],dp[j]+1);
                }
            }
        }  

        return *max_element(dp.begin(),dp.end());
    }
};
相关推荐
念何架构之路4 小时前
zap采样器与性能优化内幕
算法·性能优化·哈希算法
晒太羊的猫5 小时前
hot100动态规划刷题
算法·动态规划
weixin_531094696 小时前
heap_4内存管理
java·开发语言·算法
余额瞒着我当琳6 小时前
红黑树的实现--红黑树的概念、规则、效率、结构、旋转、查找、验证
数据结构·c++·算法
程序员南飞6 小时前
win系统安装minio
java·数据结构·算法
青少儿编程课堂6 小时前
AC自动机多模式串匹配精讲:校园关键词巡检实战解析
c++·python·算法·bfs·信息学竞赛
longlongzihan7 小时前
LeetCode 5. 最长回文子串:从暴力匹配到中心扩展的思维演进
c++·算法·leetcode
waoooqwe7 小时前
问卷样本真实吗
大数据·数据库·算法·数据分析
苦瓜打怪兽7 小时前
leetcode 热题100(11. 盛最多水的容器)
python·算法·leetcode
w_zero_one8 小时前
链表(4)
java·数据结构·算法