news 2026/1/11 15:57:02

代码随想录算法第四十三天| 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进行投诉反馈,一经查实,立即删除!
网站建设 2025/12/28 2:00:41

程序员的好日子真的到头了吗?2025年后端薪资大跌,相反AI相关岗位的薪资却水涨船高!

2025年的程序员招聘市场&#xff0c;正在上演一场比剧本更魔幻的现实。成都某公司的招聘启事上写着 “会调教AI写Java代码者优先” &#xff0c;深圳科技园出现了按小时结算的“程序员灵活用工中心”。 脉脉发布的《2025年度人才迁徙报告》显示&#xff0c;高薪岗位TOP20的平均…

作者头像 李华
网站建设 2026/1/5 23:25:33

基于Springboot+Vue超市仓库管理系统(完整源码+万字论文+答辩PPT)

作者贡献介绍 &#x1f497;CSDN从事毕设辅导第一人&#xff0c;本着诚信、靠谱、质量在业界获得优秀口碑&#xff0c;在此非常希望和行业内的前辈交流学习&#xff0c;欢迎成考学历咨询老师、大学老师前来合作交流&#x1f497; 2013年&#xff0c;正式踏入技术写作领域&…

作者头像 李华
网站建设 2025/12/17 21:48:38

教育软件用户体验测试:策略、挑战与最佳实践‌

教育软件的独特性与测试需求 教育软件作为数字化学习生态的核心&#xff0c;其用户体验&#xff08;UX&#xff09;直接影响学习成效和用户黏性。与传统软件不同&#xff0c;教育软件需兼顾教学性、互动性和易用性&#xff0c;例如在K-12或职业培训场景中&#xff0c;界面设计…

作者头像 李华
网站建设 2026/1/4 16:19:27

【ACWing】151. 表达式计算4

题目地址&#xff1a; https://www.acwing.com/problem/content/description/153/ 给出一个表达式,其中运算符仅包含,-,*,/,^&#xff08;加 减 乘 整除 乘方&#xff09;要求求出表达式的最终值。 数据可能会出现括号情况&#xff0c;还有可能出现多余括号情况。 数据保证不…

作者头像 李华
网站建设 2026/1/8 20:23:22

自动化测试的三种核心模式:策略选择与实践洞察

在敏捷开发与DevOps实践成为主流的当下&#xff0c;自动化测试已成为保障软件质量、加速产品迭代的关键环节。据行业报告显示&#xff0c;实施有效自动化测试的团队产品发布周期平均缩短40%。本文将深入解析基于界面的录制回放、数据驱动测试与关键字驱动测试这三种主流自动化测…

作者头像 李华