当前位置: 首页 > news >正文

LeetCode算法日记 - Day 89: 最长递增子序列

目录

1. 最长递增子序列

1.1 题目解析

1.2 解法

1.3 代码实现


1. 最长递增子序列

https://leetcode.cn/problems/longest-increasing-subsequence/

给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。

子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。

示例 1:

输入:nums = [10,9,2,5,3,7,101,18]
输出:4
解释:最长递增子序列是 [2,3,7,101],因此长度为 4 。

示例 2:

输入:nums = [0,1,0,3,2,3]
输出:4

示例 3:

输入:nums = [7,7,7,7,7,7,7]
输出:1

提示:

  • 1 <= nums.length <= 2500
  • -104 <= nums[i] <= 104

进阶:

  • 你能将算法的时间复杂度降低到 O(n log(n)) 吗?

1.1 题目解析

题目本质
这道题要解决的核心问题是:从数组中挑选出一些数字(保持原顺序),使得它们严格递增,求最多能挑几个。注意这里是"子序列"不是"子数组",意味着不需要连续,只要相对位置不变就行。

常规解法
最直观的想法是:暴力枚举所有可能的子序列,检查每个是否递增,记录最长的。比如对于 [10,9,2,5],要检查 [10]、[10,9]、[10,2]、[9,2]、[2,5]、[10,9,2]... 所有组合。

问题分析
暴力法的问题在于组合数太多。长度为 n 的数组有 2n2n 个子序列,每次还要检查是否递增,时间复杂度 O(2^n⋅n),当 n=2500 时根本跑不动。

思路转折
要想高效 → 必须避免重复计算 → 用动态规划。
关键洞察:如果我知道前面每个位置能组成的最长递增序列,当前位置就可以直接利用这些结果。具体来说,站在位置 i 时:

  • 回头看所有位置 j < i

  • 如果 nums[i] > nums[j],说明可以把 nums[i] 接在 j 位置的序列后面

  • 接上后长度变成 dp[j] + 1

  • 遍历所有可能的 j,选长度最大的

这样每个位置只算一次,复杂度降到 O(n^2) 可以通过。

1.2 解法

算法思想

定义 dp[i] = 以 nums[i] 结尾的最长递增子序列长度

递推公式:

dp[i] = max(dp[j] + 1)  其中 j < i 且 nums[i] > nums[j]初始值:dp[i] = 1  (每个元素自己就是长度1)

i)初始化 dp 数组,所有值设为 1(每个元素单独都是长度1的序列)

ii)外层循环:从左到右遍历每个位置 i(从1到n-1)

iii)内层循环:对于当前位置 i,遍历它前面的所有位置 j(从0到i-1)

  • 如果 nums[i] > nums[j],说明可以接在 j 后面

  • 更新 dp[i] = Math.max(dp[i], dp[j] + 1)

iv)遍历整个 dp 数组,找出最大值作为答案

易错点

  • 误以为只看相邻元素:新手容易写成 if(nums[i] > nums[i-1]),但递增子序列不要求连续,必须遍历所有 j < i

  • 忘记初始化为1:如果初始化为0,即使找不到可接的位置,dp[i] 也应该是1(元素自己),所以必须 Arrays.fill(dp, 1)

  • 直接返回 dp[n-1]:dp[i] 只表示"以i结尾"的长度,最长序列不一定在最后,必须取 max(dp)

  • 边界条件:外层循环从 i=1 开始(i=0 时没有前面的元素可比较),但要确保 n=1 时能正确返回1

1.3 代码实现

class Solution {public int lengthOfLIS(int[] nums) {int n = nums.length;int[] dp = new int[n];Arrays.fill(dp, 1);  // 初始化:每个元素单独都是长度1// 从第二个元素开始遍历for(int i = 1; i < n; i++){// 回头看所有前面的位置for(int j = 0; j < i; j++){// 如果能接在j后面,更新最大长度if(nums[i] > nums[j]){dp[i] = Math.max(dp[i], dp[j] + 1);}}}// 找出所有位置中的最大值int ret = 0;for(int x : dp){ret = Math.max(ret, x);}return ret;}
}

复杂度分析

  • 时间复杂度:O(n^2),两层循环,外层 n 次,内层最多 n 次

  • 空间复杂度:O(n),需要 dp 数组存储每个位置的结果

http://www.dtcms.com/a/557152.html

相关文章:

  • 两学一做 网站帮别人建网站赚钱吗
  • 2025江苏省职业院校技能大赛网络系统管理赛项模块A:网络构建卷I(未公开)
  • 鸿蒙工程结构、开发指南
  • Python为什么能成为Ubuntu官方支持的脚本语言?
  • Studio Drummer 深度指南:从采样逻辑到风格化创作的实战手册
  • 一个专门做试题的网站商品seo关键词优化
  • 汽车ECU测试中边界值方法
  • 微信小程序开发工具软件网络优化策划书
  • 【GSR】皮肤电反应 数据分析全流程教程
  • 现代Python开发环境搭建(VSCode + Dev Containers)
  • 网站模版如何使用个人网站经营性备案查询
  • 理解计算机系统_程序计数器PC的实现
  • 在Unity中运行Yolo推理
  • php+redis基本操作及操作说明
  • 神经网络补充知识
  • 怎么在网站后台删除图片vps搭建网站教程
  • MySQL主从数据一致性校验工具:pt-table-checksum 详解
  • 源码分享:AI照片风格化小程序
  • 哪些行业做网站的多如何做二级域名子目录网站
  • jQuery Mobile 面板
  • Vulfocus---shiro反序列化漏洞
  • 搭建以Node-RED为基础的“小快灵”智能工厂OT底座的实现框架
  • 三防平板三防是指哪三防?适合应用在什么场景?
  • <数据集>yolo织物缺陷识别数据集<目标检测>
  • ubuntu中安装多版本esp-idf环境
  • 网站建设与管理相关工作岗位智慧团建在线登录
  • 从依赖地狱到仓库中枢:Nexus让包管理像逛超市一样简单
  • 用pw后缀的网站今天广西紧急通知最新
  • 果合gohe网站建设网站的互动功能
  • php做网站模板wordpress 顶部导航条