力扣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 数组
    • 外层循环:i0n-1(当前要计算的元素)
    • 内层循环:j0i-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());
    }
};
相关推荐
伊玛目的门徒6 小时前
试用leetcode之典中典 二数之和问题
java·算法·leetcode
Jerry6 小时前
LeetCode 226. 翻转二叉树
算法
想做小南娘,发现自己是女生喵8 小时前
【无标题】
数据结构·算法
Kx_Triumphs9 小时前
HDU4348 To the moon(主席树区间修改模板)
算法·题解
旖-旎10 小时前
《LeetCode647 回文子串 || LeetCode 5 最长回文子串》
c++·算法·leetcode·动态规划·哈希算法
轻颂呀11 小时前
约瑟夫环问题
算法
科技大视界12 小时前
投资AI项目,传统尽调不够用了——李章虎律师拆解算法、数据、算力三大雷区
人工智能·算法·数据挖掘
郝学胜-神的一滴13 小时前
算法实战:最小k个数——大顶堆的优雅解法
开发语言·数据结构·c++·python·程序人生·算法·排序算法
Irissgwe13 小时前
算法滑动窗口
数据结构·算法