动态规划求解leetcode300.最长递增子序列(LIS)详解

给你一个整数数组 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

关键点

  • 双重循环结构:外层循环遍历每个元素作为子序列结尾,内层循环检查所有可能的前驱元素

  • 递增条件:只有当 nums[j] < nums[i] 时才考虑状态转移

  • 时间复杂度:O(n²),因为有两层嵌套循环

核心思路

  1. 定义状态

    • dp[i] 表示以 nums[i] 结尾的最长递增子序列的长度

    • 初始时每个元素本身就是一个长度为1的子序列,所以初始化 dp 数组全为1

  2. 状态转移

    • 对于每个 i(当前元素),检查所有 j < i(前面的元素)

    • 如果 nums[j] < nums[i](满足递增条件),则尝试更新 dp[i]

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

      这表示如果接在 nums[j] 后面能形成更长的子序列,就更新 dp[i]

  3. 记录结果

    • 在计算过程中持续维护一个全局最大值 res

    • 最终 res 就是整个数组的最长递增子序列长度

// Dynamic programming.
class Solution {public int lengthOfLIS(int[] nums) {if(nums.length == 0) return 0;int[] dp = new int[nums.length];int res = 0;Arrays.fill(dp, 1);for(int i = 0; i < nums.length; i++) {for(int j = 0; j < i; j++) {if(nums[j] < nums[i]) dp[i] = Math.max(dp[i], dp[j] + 1);}res = Math.max(res, dp[i]);}return res;}
}

示例数组

nums = [10, 9, 2, 5, 3, 7, 101, 18]

算法步骤解析

  1. 初始化

    • 创建dp数组,长度与nums相同,初始值全为1(因为每个元素本身就是一个长度为1的子序列)

    dp = [1, 1, 1, 1, 1, 1, 1, 1]
  2. 双重循环处理

    • 外层循环:i从0到n-1

    • 内层循环:j从0到i-1

  3. 逐步计算过程

    i=0 (nums[0]=10):

    • j无(因为i=0时j从0到-1)

    • dp保持不变:[1, 1, 1, 1, 1, 1, 1, 1]

    • res=1

    i=1 (nums[1]=9):

    • j=0: nums[0]=10 > nums[1]=9 → 不更新

    • dp保持不变:[1, 1, 1, 1, 1, 1, 1, 1]

    • res=1

    i=2 (nums[2]=2):

    • j=0: nums[0]=10 > nums[2]=2 → 不更新

    • j=1: nums[1]=9 > nums[2]=2 → 不更新

    • dp保持不变:[1, 1, 1, 1, 1, 1, 1, 1]

    • res=1

    i=3 (nums[3]=5):

    • j=0: nums[0]=10 > nums[3]=5 → 不更新

    • j=1: nums[1]=9 > nums[3]=5 → 不更新

    • j=2: nums[2]=2 < nums[3]=5 → dp[3] = max(dp[3], dp[2]+1) = max(1, 2) = 2

    • dp更新为:[1, 1, 1, 2, 1, 1, 1, 1]

    • res=2

    i=4 (nums[4]=3):

    • j=0: nums[0]=10 > nums[4]=3 → 不更新

    • j=1: nums[1]=9 > nums[4]=3 → 不更新

    • j=2: nums[2]=2 < nums[4]=3 → dp[4] = max(dp[4], dp[2]+1) = max(1, 2) = 2

    • j=3: nums[3]=5 > nums[4]=3 → 不更新

    • dp更新为:[1, 1, 1, 2, 2, 1, 1, 1]

    • res=2

    i=5 (nums[5]=7):

    • j=0: nums[0]=10 > nums[5]=7 → 不更新

    • j=1: nums[1]=9 > nums[5]=7 → 不更新

    • j=2: nums[2]=2 < nums[5]=7 → dp[5] = max(dp[5], dp[2]+1) = max(1, 2) = 2

    • j=3: nums[3]=5 < nums[5]=7 → dp[5] = max(dp[5], dp[3]+1) = max(2, 3) = 3

    • j=4: nums[4]=3 < nums[5]=7 → dp[5] = max(dp[5], dp[4]+1) = max(3, 3) = 3

    • dp更新为:[1, 1, 1, 2, 2, 3, 1, 1]

    • res=3

    i=6 (nums[6]=101):

    • j=0: nums[0]=10 < nums[6]=101 → dp[6] = max(dp[6], dp[0]+1) = max(1, 2) = 2

    • j=1: nums[1]=9 < nums[6]=101 → dp[6] = max(dp[6], dp[1]+1) = max(2, 2) = 2

    • j=2: nums[2]=2 < nums[6]=101 → dp[6] = max(dp[6], dp[2]+1) = max(2, 2) = 2

    • j=3: nums[3]=5 < nums[6]=101 → dp[6] = max(dp[6], dp[3]+1) = max(2, 3) = 3

    • j=4: nums[4]=3 < nums[6]=101 → dp[6] = max(dp[6], dp[4]+1) = max(3, 3) = 3

    • j=5: nums[5]=7 < nums[6]=101 → dp[6] = max(dp[6], dp[5]+1) = max(3, 4) = 4

    • dp更新为:[1, 1, 1, 2, 2, 3, 4, 1]

    • res=4

    i=7 (nums[7]=18):

    • j=0: nums[0]=10 < nums[7]=18 → dp[7] = max(dp[7], dp[0]+1) = max(1, 2) = 2

    • j=1: nums[1]=9 < nums[7]=18 → dp[7] = max(dp[7], dp[1]+1) = max(2, 2) = 2

    • j=2: nums[2]=2 < nums[7]=18 → dp[7] = max(dp[7], dp[2]+1) = max(2, 2) = 2

    • j=3: nums[3]=5 < nums[7]=18 → dp[7] = max(dp[7], dp[3]+1) = max(2, 3) = 3

    • j=4: nums[4]=3 < nums[7]=18 → dp[7] = max(dp[7], dp[4]+1) = max(3, 3) = 3

    • j=5: nums[5]=7 < nums[7]=18 → dp[7] = max(dp[7], dp[5]+1) = max(3, 4) = 4

    • j=6: nums[6]=101 > nums[7]=18 → 不更新

    • dp更新为:[1, 1, 1, 2, 2, 3, 4, 4]

    • res=4

最终结果

最长递增子序列的长度为4。对应的子序列可以是:

  • [2, 3, 7, 101]

  • 或 [2, 5, 7, 101]

  • 或 [2, 3, 7, 18]

  • 或 [2, 5, 7, 18]

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/80765.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Rule.resourceQuery(通过路径参数指定loader匹配规则)

1. 说明 在 webpack 4 中&#xff0c;Rule.resourceQuery 是一个用于根据文件路径中的 查询参数&#xff08;query string&#xff09; 来匹配资源的配置项。它允许你针对带有特定查询条件的文件&#xff08;如 file.css?inline 或 image.png?raw&#xff09;应用不同的加载…

快速上手 MetaGPT

1. MetaGPT 简介 在当下的大模型应用开发领域&#xff0c;Agent 无疑是最炙手可热的方向&#xff0c;这也直接催生出了众多的 Agent 开发框架。在这之中&#xff0c; MetaGPT 是成熟度最高、使用最广泛的开发框架之一。 MetaGPT 是一款备受瞩目的多智能体开发框架&#xff0c…

新闻数据接口开发指南:从多源聚合到NLP摘要生成

随着人工智能&#xff08;AI&#xff09;技术的飞速发展&#xff0c;新闻行业也迎来了新的变革。AI不仅能够自动化生成新闻内容&#xff0c;还能通过智能推荐系统为用户提供个性化的新闻体验。万维易源提供的“新闻查询”API接口&#xff0c;结合了最新的AI技术&#xff0c;为开…

每天五分钟深度学习框架pytorch:使用visdom绘制损失函数图像

visdom的安装 pip install visdom如果安装失败 pip install --upgrade visdom开启visdom python -m visdom.server nohup python -m visdom.server后台启动然后就会出现,下面的页面,我们可以使用下面的链接打开visdom页面 Visdom中有两个重要概念: env环境。不同环境的可…

UnityEditor - 调用编辑器菜单功能

例如: 调用Edit/Frame Selected In Scene EditorApplication.ExecuteMenuItem("Edit/Frame Selected in Scene"); EditorApplication.ExecuteMenuItem("Edit/Lock view to Selected");

电化学-论文分享-NanoStat: An open source, fully wireless potentiostat

电化学-论文分享-NanoStat: An open source, fully wireless potentiostat 发现了一篇近期有关便携式电化学工作站相关方面的论文&#xff08;2022&#xff09;&#xff0c;并且全部工作内容都是开源的&#xff0c;硬件电路图、PCB板、嵌入式代码以及网页代码、设备外壳所有资…

ZYNQ----------PS端入门(四)(根文件系统进emmc,镜像和设备树进flash)

文章目录 系列文章目录前言一、根文件系统是什么&#xff1f;二、根文件系统烧进emmc1.emmc是什么&#xff1f;2.根文件系统的位置3.分离根文件系统步骤1.14.分离根文件系统步骤1.25.分离根文件系统步骤2.1 三、根文件系统进emmc&#xff0c;设备树和镜像进flash 系列文章目录 …

uniapp+vue3移动端实现输入验证码

ios安卓 uniappvue3 微信小程序端 <template><view class"verification-code"><view class"verification-code__display"><block v-for"i in numberArr" :key"i"><view:class"[verification-code__d…

如何选择游戏支付平台呢?

如果要选择一个游戏支付平台的话&#xff0c;那么你可以考虑一下这个平台&#xff1a;功能非常多&#xff0c;支付模式很高效&#xff0c;功能很全&#xff0c;服务很贴心&#xff0c;资金安全靠得住&#xff0c;安全认证模式也很可靠。 第二&#xff0c;结算方法也很多&#x…

前端如何获取文件的 Hash 值?多种方式详解、对比与实践指南

文章目录 前言一、Hash 值为何重要&#xff1f;二、Hash 值基础知识2.1 什么是 Hash&#xff1f;2.2 Hash 在前端的应用场景2.3 常见的 Hash 算法&#xff08;MD5、SHA 系列&#xff09; 三、前端获取文件 Hash 的常用方式3.1 使用 SparkMD5 计算 MD5 值3.2 使用 Web Crypto AP…

【Java学习笔记】类与对象

类与对象 什么是类&#xff1f; 知识迁移&#xff1a;类比 C 语言中的结构体 类的描述 类是一个对象的抽象&#xff0c;从字面意思就表示一个类的事物&#xff0c;类具有属性和方法&#xff08;行为&#xff09;&#xff0c;对象是类的一个具体表现 总结&#xff1a;类是对象…

如何对极狐GitLab 议题进行过滤和排序?

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;关于中文参考文档和资料有&#xff1a; 极狐GitLab 中文文档极狐GitLab 中文论坛极狐GitLab 官网 排序和议题列表排序 (BASIC ALL) 您可以通过多种方式对议题列表进行排序&#xff0c;可用的排序选项可以根据列表的上下文进…

k8s中资源的介绍及标准资源namespaces实践

文章目录 第1章 k8s中的资源(resources)介绍1.1 k8s中资源(resouces)的分类1.2 k8s中资源(resources)的级别1.3 k8s中资源(resources)的API规范1.4 k8s中资源(resources)的manifests 第2章 k8s中的标准资源之namespaces的实践2.1 基本介绍2.2 编写相关ns资源对象的manifests2.3…

优化uniappx页面性能,处理页面滑动卡顿问题

问题&#xff1a;在页面遇到滑动特别卡的情况就是在页面使用了动态样式或者动态类&#xff0c;做切换的时候页面重新渲染导致页面滑动卡顿 解决&#xff1a;把动态样式和动态类做的样式切换改为通过获取元素修改样式属性值 循环修改样式示例 bannerList.forEach((_, index)…

DeepSeek赋能Nuclei:打造网络安全检测的“超级助手”

引言 各位少侠&#xff0c;周末快乐&#xff0c;幸会幸会&#xff01; 今天唠一个超酷的技术组合——用AI大模型给Nuclei开挂&#xff0c;提升漏洞检测能力&#xff01; 想象一下&#xff0c;当出现新漏洞时&#xff0c;少侠们经常需要根据Nuclei模板&#xff0c;手动扒漏洞文章…

leetcode - 字符串

字符串 466. 统计重复个数 题目 定义 str [s, n] 表示 str 由 n 个字符串 s 连接构成。 例如&#xff0c;str ["abc", 3] "abcabcabc" 。 如果可以从 s2( )中删除某些字符使其变为 s1&#xff0c;则称字符串 s1( )可以从字符串 s2 获得。 例如&#xf…

Java求职者面试:从Spring Boot到微服务的技术深度探索

场景&#xff1a;互联网大厂Java求职者面试 角色介绍&#xff1a; 面试官&#xff1a;技术精湛&#xff0c;负责把控面试质量。谢飞机&#xff1a;搞笑的程序员&#xff0c;偶尔能答对问题。 第一轮&#xff1a;基础知识 面试官&#xff1a;谢飞机&#xff0c;你能简要介绍…

榕壹云国际版短剧系统:基于Spring Boot+MySQL+UniApp的全球短剧创作平台

一、项目背景与简介 在短视频行业高速发展的今天&#xff0c;短剧内容已成为全球用户娱乐消费的新宠。为满足市场对高质量、多样化短剧的需求&#xff0c;我们基于Spring Boot MySQL UniApp技术栈开发了榕壹云国际版短剧系统&#xff0c;这是一款面向全球市场的短剧创作与分…

资料分享!瑞芯微RK3506(3核ARM+Cortex-A7 + ARM Cortex-M0)工业评估板硬件资料

前 言 本文主要介绍TL3506-EVM评估板硬件接口资源以及设计注意事项等内容。 RK3506J/RK3506B处理器的IO电平标准一般为1.8V、3.3V,上拉电源一般不超过3.3V或1.8V,当外接信号电平与IO电平不匹配时,中间需增加电平转换芯片或信号隔离芯片。按键或接口需考虑ESD设计,ESD器…

C#通过NTP服务器获取NTP时间

C#通过NTP服务器获取NTP时间 注意事项&#xff1a; 如果NTP服务器地址是域名&#xff0c;如阿里云的NTP服务器地址。需要DNS解析。NTP使用UDP通讯&#xff0c;默认端口是123NTP经过很多年的发展&#xff0c;有4个版本号&#xff0c;目前常用的3和4。NTP区分客户端和服务端&am…