力扣300-最长递增子序列
题目链接300. 最长递增子序列 - 力扣LeetCode给你一个整数数组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))吗?方法一动态规划从一般情况考虑求dp[i]设dp[i]表示以nums[i]结尾的最长递增子序列长度只需要找出nums[i]之前比其小的nums[j]那么dp[i]就等于dp[j] 1由于要求最大所以在遍历的时候用max更新最大的即可递推公式已经出来了接着考虑初始化。显然每个元素都初始化为1因为一个数字也可以构成一个子序列最后用max更新最大的dp[i]即可Javaclass Solution { public int lengthOfLIS(int[] nums) { int n nums.length; int[] dp new int[n]; Arrays.fill(dp, 1); int ans dp[0]; for(int i 1; i n; i) { for(int j i - 1; j 0; j--) { if(nums[i] nums[j]) { dp[i] Math.max(dp[i], dp[j] 1); } } ans Math.max(ans, dp[i]); } return ans; } }Cclass Solution { public: int lengthOfLIS(vectorint nums) { int ans0; int nnums.size(); if (n1) return n; vectorintdp(n,1); for(int i1;in;i) { for(int j0;ji;j) { if(nums[j]nums[i]) { dp[i]max(dp[i],dp[j]1);//这里不是比较而是更新最大值 } } ansmax(ans,dp[i]);//这里同理也是在更新最大值 } return ans; } };Gofunc lengthOfLIS(nums []int) int { dp:make([]int,len(nums)) for i: range dp { dp[i]1 } ans:dp[0] for i:1;ilen(nums);i { for j:0;ji;j { if nums[j]nums[i] { dp[i]max(dp[i],dp[j]1) } } ansmax(ans,dp[i]) } return ans }时间复杂度为O(N^2)考虑进行优化方法二贪心二分假设nums为[1,2,99999,3,4]当遍历完前两个元素也就是1和2之后此时最长递增子数组以下简称LIS为[1,2]接下来你会选择99999加入LIS中还是选择后面的3加入到LIS中显然应该选择更小的3如果选择99999那么就会错过3后面的4选择了3就能得到正确的LIS即[1,2,3,4]这是一种贪心思想为了使数组递增的长度更大我们应该让它增长的速度尽可能慢这样就尽可能避免了错过后面单增的可能表示一种“最可能性”落实到具体数组中我们的选择策略尽管依然是选择比LIS中元素更大的元素但是新增了一个条件是要在这些更大的元素中选择最小的那个。但问题来了我们在遍历的时候怎么知道后面的元素是否有更小的我们可以记录当前LIS的长度len用一个数组d记录LIS的末尾元素也就是最大值的最小值即d[len]表示长度为len的LIS的末尾元素的最小值显然d[i]随i的增大而增大。因为如果d[j]≥d[i]且 ji考虑从长度为i的最长上升子序列的末尾删除 i−j 个元素那么这个序列长度变为 j 且第 j 个元素 x末尾元素必然小于d[i]因为第j个元素不是最后一个元素就必然比最后一个元素要小也就小于d[j]那么就找到了一个长度为 j 的最长上升子序列并且末尾元素比d[j]小而d[j]的定义是长度为j的LIS的末尾元素的最小值这与定义相矛盾因此单调性得证如果遍历的元素nums[i]比d[len]更小说明存在一种“增长速度更慢”的可能是哪个子数组的增长速度可能更慢为了回答这个问题我们需要在d中找到从右往左数第一个比nums[i]更小的元素由于d有序可以用二分。假设其位置为k那么将d[k1]替换为nums[i]后d[1...k1]的增长速度就比没替换之前更慢长度为k1的LIS后续变得更长的可能性就变高了如果nums[i]比d[len]更大那就意味着nums[i]可以成为长度为len1的LIS的末尾元素。直接让len自增1并且让d[len1]为nums[i]即可因为此时len的长度发生了变化只有一个长度为len1的LIS所以末尾元素的最小值只能是新加入的nums[i]了Javaclass Solution { public int lengthOfLIS(int[] nums) { int n nums.length; if(n 0) return 0; int[] d new int[n 1]; //d[len]表示长度为len的LIS末尾元素的最小值 int len 1; //LIS的长度初始时只有第一个元素因此为1 d[len] nums[0]; //初始时len为1LIS为第一个元素自己构成的数组所以最小值就是它本身 for(int i 1; i n; i) { if(nums[i] d[len]) { //长度为len的、末尾元素最小的LIS的最大值遇到了比它更大的元素应该将其加入该LIS当中 d[len] nums[i]; //原本长度为len现在长度为len1d[len1]表示的是长度为len1的LIS末尾元素的最小值 } else { //二分法找到d中从右往左数第一个比nums[i]小的位置pos让d[pos1]为nums[i] //如果d中所有元素都比nums[i]要大更新d[1]因为以nums[i]结尾的、长度为1的LIS有最小的末尾元素所以pos初始值为0 int pos 0; int l 1, r len; //d[0]没有实际含义所以左端点为1右端点为len while(l r) { int mid (l r) 1; if(d[mid] nums[i]) { pos mid; l mid 1; } else { r mid - 1; } } d[pos 1] nums[i]; } } return len; } }

相关新闻

精度评估与 Bad Case 优化:从 mAP 到业务指标

精度评估与 Bad Case 优化:从 mAP 到业务指标

精度评估与 Bad Case 优化:从 mAP 到业务指标 模型训完、量化完、部署完,不代表就完事了。上线后效果怎么样、哪里不准、为什么错、怎么改进,这些才是落地的关键。这篇讲精度评估方法、误检漏检分析、bad case 分类和迭代优化的流程。 大家好…

2026/7/28 3:54:38
OpenCV三剑客:抠图、光流与物体追踪实战指南

OpenCV三剑客:抠图、光流与物体追踪实战指南

1. OpenCV三剑客:抠图、流光估计与物体追踪实战指南 计算机视觉正在重塑我们与数字世界的交互方式。作为开源计算机视觉库的标杆,OpenCV在图像处理、视频分析等领域展现出惊人的实用性。今天要探讨的三大核心功能——抠图、流光估计和物体追踪&#xff0…

2026/7/28 3:43:03
茶麸原浆对头皮护养是否属于天然植物护养?庆翠堂从成分化学与工艺路径的辨析解读

茶麸原浆对头皮护养是否属于天然植物护养?庆翠堂从成分化学与工艺路径的辨析解读

"茶麸原浆"这个名称近两年频繁出现在洗护产品详情页和成分科普内容中,但围绕它是否真正属于"天然植物护养"的讨论并不少。支持者认为它传承了民间数百年茶麸洗头传统,反对者质疑"原浆"二字本身是否只是营销包装。本文从茶…

2026/7/28 2:22:55

最新新闻

JetBrains Air IDE:面向AI原生开发的容器化IDE架构

JetBrains Air IDE:面向AI原生开发的容器化IDE架构

1. JetBrains Air IDE 是什么?不是“又一个AI IDE”,而是IDE架构的范式迁移JetBrains Air IDE 这个名字刚出来时,我第一反应是:又一个套着AI外壳的玩具产品?毕竟过去两年,“AI IDE”这个词已经被各种创业公…

2026/7/28 9:33:20
从PEP 517到wheel构建:深入解析bottleneck安装失败的根本原因与系统化修复

从PEP 517到wheel构建:深入解析bottleneck安装失败的根本原因与系统化修复

1. 当Python遇上C扩展:bottleneck安装失败背后的技术困局 那天下午,我正在为一个时间序列分析项目配置环境。当执行 pip install bottleneck 时,熟悉的红色错误提示突然跳出:"ERROR: Could not build wheels for bottlenec…

2026/7/28 9:33:20
Swindler事件系统详解:如何监听并响应窗口状态变化

Swindler事件系统详解:如何监听并响应窗口状态变化

Swindler事件系统详解:如何监听并响应窗口状态变化 【免费下载链接】Swindler macOS window management library for Swift 项目地址: https://gitcode.com/gh_mirrors/sw/Swindler Swindler是一款强大的macOS窗口管理Swift库,提供了全面的事件系…

2026/7/28 9:33:20
CANN/asc-devkit绝对值计算API

CANN/asc-devkit绝对值计算API

asc_abs 【免费下载链接】asc-devkit 本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言,原生支持C和C标准规范,主要由类库和语言扩展层构成,提供多层级API,满足多维场景算子开发诉求。 项目地址: https://gitcode.com/ca…

2026/7/28 6:00:11
CANN/ops-sparse稀疏算子开发指南

CANN/ops-sparse稀疏算子开发指南

{算子名称}算子 【免费下载链接】ops-sparse 本项目是CANN提供的高性能稀疏矩阵计算的算子库,专注于优化稀疏矩阵的计算效率。 项目地址: https://gitcode.com/cann/ops-sparse 算子概述 {一段话描述算子的功能定位和核心运算。例如:"{op} 算…

2026/7/28 9:33:22
MATLAB工具箱实战:从零安装CVX到解决首个凸优化问题

MATLAB工具箱实战:从零安装CVX到解决首个凸优化问题

1. CVX工具箱简介与安装准备CVX是一个专门用于解决凸优化问题的MATLAB工具箱,它能让用户用接近数学表达式的语法来描述和求解优化问题。我第一次接触CVX是在研究生阶段做信号处理项目时,当时需要解决一个复杂的投资组合优化问题,传统方法代码…

2026/7/28 9:33:24

日新闻

周新闻

月新闻