news 2026/6/21 13:14:14

代码随想录算法第四十三天| LeetCode300最长递增子序列、LeetCode674最长连续递增序列、Leetcode718最长重复子数组

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
代码随想录算法第四十三天| LeetCode300最长递增子序列、LeetCode674最长连续递增序列、Leetcode718最长重复子数组

LeetCode 300 最长递增子序列

题目链接:300.最长递增子序列

文档讲解:代码随想录

视频讲解:最长递增子序列

思路与感想:这道题目我先根据题意要求最长递增子序列的长度,确定了dp值应该就是这个最大长度,然后考虑dp[i]中的i究竟代表什么意思,考虑到递推公式累加的时候肯定是最长递增子序列中新遍历的这个元素可以被合法添入子序列末尾,那与之比较的应该是上一个阶段子序列元素中的末尾,由此确定要想实现累加,取决于子序列中旧末尾元素和可能成为新末尾的元素之间的大小,所以我猜想这个dp[i]的含义就是以nums[i]为末尾元素的子序列的最大长度。原本以为明确了dp数组确定递推公式就很简单了,后面却想错了,目光只局限在了dp[i]和dp[i - 1]上面了,还是没有深刻理解到dp数组的含义,末尾元素不一定要是当前遍历元素的前一个元素,只要是下标0到i-1都是可以的,但我们需要求dp[0] + 1到dp[i - 1] + 1这i个值里面的最大值,即最长递增子序列。加一就是把第i个元素也算上,然后有一个if条件只有元素i大于元素j才进行递推。在遍历的过程中随时记录dp[i]的最大值,这个时候不一定是最后一个元素为末尾的时候最大,所以要在所有dp值里面找最大值。

收获:1.子序列问题的递推公式

class Solution { public int lengthOfLIS(int[] nums) { if (nums.length <= 1) { // 特殊情况处理 return nums.length; } int[] dp = new int[nums.length]; // dp[i]表示严格递增子序列中末尾元素为nums[i]的最长长度 Arrays.fill(dp,1); // 初始化dp只有一个元素长度就为1 int result = 1; // 记录最大长度 for (int i = 1; i < nums.length; i++) { for (int j = 0; j < i; j++) { // 递推dp[i]需要遍历nums[0]到nums[i - 1] if (nums[i] > nums[j]) { // 对于末尾元素小于nums[i]的才进行递推更新dp[i] dp[i] = Math.max(dp[i],dp[j] + 1); // 这个过程实际上是在遍历0到i - 1,末尾元素小于nums[i]的情况下,它们各自dp值的最大值,即dp[j]的最大值,而不是比较dp[i]和dp[j] + 1,每个+1是因为加了元素i这个末尾元素 } } result = Math.max(result,dp[i]); //更新最大长度 } return result; } }

LeetCode 674 最长连续递增序列

题目链接:674.最长连续递增序列

文档讲解:代码随想录

视频讲解:最长连续递增序列

思路与感想:这道题目很简单因为子序列是要求连续的。于是我定义了result和size两个变量,只要元素i大于元素i-1的话size就自增,反之size就重置为1,然后每次遍历一个元素处理完size后result都实时更新成最大值。写完这种模拟的方法后再去想动态规划写法,其实也一下子就写出来了,把dp[i]的下标定义为最后一个元素为nums[i]的时候子序列的长度即可,因为是连续的所有只要考虑元素i和它前一个元素i-1大小即可,只有当元素i大于i - 1的时候才递推dp[i] = dp[i - 1] + 1,我最初的代码还写了else dp[i] = 1,其实这步没必要因为初始化的时候每个dp值都为1了。这道题目跟上一道题的区别在于子序列是不是要求连续,上一题理解起来很困难,而且我一开始的做法只想着比较i和i-1,其本质上就是把子序列当成要求连续来写了,但实际上上一题是可以不连续的,所以才要把i之前的dp值都遍历一遍求最大值。但这一道题要求连续所以只需要比较元素i和i-1即可,满足就加1,不满足重头再来累计。

收获:1.子序列连续与不连续递推公式的差别

// 动态规划 class Solution { public int findLengthOfLCIS(int[] nums) { int result = 1; // 记录最终结果 int size = 1; // 记录当前子序列大小 for (int i = 1; i < nums.length; i++) { if (nums[i] > nums[i - 1]) { // 如果当前元素比前一个元素大就加入子序列,size++ size++; } else { size = 1; // 如果不是的话就得重置子序列长度 } result = Math.max(result,size); // 每次都更新result保证其为最大值 } return result; } }
// 模拟法 class Solution { public int findLengthOfLCIS(int[] nums) { int result = 1; // 记录最终结果 int size = 1; // 记录当前子序列大小 for (int i = 1; i < nums.length; i++) { if (nums[i] > nums[i - 1]) { // 如果当前元素比前一个元素大就加入子序列,size++ size++; } else { size = 1; // 如果不是的话就得重置子序列长度 } result = Math.max(result,size); // 每次都更新result保证其为最大值 } return result; } }

LeetCode 718 最长重复子数组

题目链接:718.最长重复子数组

文档讲解:代码随想录

视频讲解:最长重复子数组

思路与感想:这道题目真的挺难,首先也就是这个二维的DP数组的含义虽然经过提示和之前题目的积累可以想出来,虽然想出来的比较直接就是以i,j结尾,但是也可以写出来照理说,不过递推公式就没想出来,一个是因为这个DP数组含义确实没太理清楚,另一个原因是二维DP的题目有段时间没做过有点不习惯,后面给我了递推公式我也想了好一会,一切都还是要建立在这两层for循环里面理解然后画图才清晰。接下来就是每次获得一个dp值就尝试更新result。卡哥把dp数组定义为以i-1和j-1结尾很巧妙,规避了初始化和循环的时候判断边界的操作冗余。这道题也有压缩DP数组的一维滚动数组的解法。相比于二维DP循环内递推的时候要多一个else让dp值为0,然后下一轮循环就鉴于上一轮留下了的数组进行计算,之所以可以这么做的原因就是每一个dp值是根据他的左上角那个即横纵坐标同时减一后那个dp值递推来的,要注意的是内层for循环要倒序,避免取到重复的值。

收获:1.重温二维DP和滚动数组压缩的写法;2.递推公式真难想

class Solution { public int findLength(int[] nums1, int[] nums2) { int[][] dp = new int[nums1.length + 1][nums2.length + 1]; // dp[i][j]的含义是在nums1数组中以i - 1为结尾,在nums2数组中以j - 1为结尾,公共长度最长的子数组长度 int result = 0; // 记录最长的长度 for (int i = 1; i <= nums1.length; i++) { for (int j = 1; j <= nums2.length; j++) { if (nums1[i - 1] == nums2[j - 1]) { // nums1[i - 1]和nums[j - 1]相同说明按照dp的定义,就可以更新dp[i][j]的值了。 dp[i][j] = dp[i - 1][j - 1] + 1; } result = Math.max(result,dp[i][j]); // 每次都更新result的值 } } return result; } }

今天算法难度一般,前两题都可以手撕,最后一题上难度了写不出来,序列问题感觉DP数组含义和递推公式都挺难想的,还是得慢慢沉淀。下午去健个身晚上回寝室接着学springboot然后看一看明天要讲的ppt,以前的内容有点忘了,不知道明天能不能讲好。今天花了大概五个小时。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/19 22:01:21

【学习心得】Python好库推荐——pyttsx3

pyttsx3&#xff08;Python Text-to-Speech eXtended version 3&#xff09;是一个跨平台的 Python 库&#xff0c;用于将文本转换为语音&#xff08;Text-to-Speech, TTS&#xff09;。它可以在不依赖互联网连接的情况下&#xff0c;在本地将文本朗读出来&#xff0c;支持 Win…

作者头像 李华
网站建设 2026/6/15 2:41:10

Linux 通用软件包 AppImage 打包详解

格式介绍 - AppImageAppImage 是 Linux 系统中一种新型的软件包格式&#xff0c;它与 rpm、deb 这些软件包格式相比最大的不同便是&#xff1a;&#xff08;1&#xff09;无需安装&#xff0c;即用即删。&#xff08;2&#xff09;只需打包一次&#xff0c;便可到处运行。完美的…

作者头像 李华
网站建设 2026/6/18 11:49:51

软件测试工具选型全景指南:从需求对齐到落地实践

为什么工具选型关乎测试成败 在快速迭代的软件开发周期中&#xff0c;测试工具已从辅助手段演进为质量保障的核心基础设施。据统计&#xff0c;超过67%的测试团队曾因工具选型不当导致项目延期或质量漏洞。2025年测试工具生态呈现两大趋势&#xff1a;AI驱动的智能测试平台快速…

作者头像 李华
网站建设 2026/6/14 3:20:31

自动化测试投资回报率(ROI)分析与实践指南

在软件开发周期不断缩短的当下&#xff0c;自动化测试已成为保障产品质量、提升测试效率的关键手段。然而&#xff0c;许多测试团队在推行自动化测试时面临共同困惑&#xff1a;如何量化自动化测试的投入产出比&#xff1f;本文将从测试从业者视角&#xff0c;深入解析自动化测…

作者头像 李华
网站建设 2026/6/20 23:41:20

企业微信群消息定时发送竟然这么简单?三步搞定让效率翻倍!

你是不是还在手动发送每天的晨会提醒&#xff1f;或者每到下班时间就急着往群里发日报&#xff1f;别折腾了&#xff0c;现在有个方法能让你彻底解放双手。想想看&#xff0c;每天固定要发的通知、报表、提醒&#xff0c;如果都能自动完成&#xff0c;那该多省心啊。连趣云控制…

作者头像 李华