代码随想录算法训练营第60期第五十天打卡

        大家好,首先感慨一下,时间过的真是快,不知不觉我们的训练营就已经到第五十天了,首先祝贺自己一直在坚持,今天是我们动态规划章节的收官之战,明天我们就会走进一个全新的算法章节单调栈,我们要为我们的动态规划章节画上一个完美的句号,那我们就开始我们今天的动态规划的题目。

第一题对应力扣编号为647的题目回文子串

        其实大家应该很熟悉什么叫回文子串了,就是倒着读和正着读是一样的,当然很明显一个字符的字符串当然是回文串,那今天的这道题目是什么意思呢?我们先一起来看一下:

        其实很明显题目是要求我们去求回文串的个数,我们就直接考虑使用动态规划的思路来解决这道题目,当然免不了要使用动规五部曲:

        第一步确定dp数组以及下标的含义:这道题目就有点不一样了,我们以前做过的绝大部分题目我们都是题目要求什么我们就定义什么,但是在这里我们如果还要定义dp[i] 为 下标i结尾的字符串有 dp[i]个回文串的话我们就会发现我们压根找不到递推关系,这样就不好了,没有递推关系我们可怎么解决这道题目?大家其实想想我们回文串dp[i]与dp[i-1]与dp[i+1]是否存在什么关系吗?好像是没有的,它们压根可以表示任意一个字符,而且还有回文串的长度也是不确定的,因此我们这时候去看回文串的关系示意图:

        我们的确使用一个变量跟本表示不了回文字符串,因此我们就需要考虑使用类似于双指针的思想,其实我们在写判断回文字符串的函数的时候我们也是会考虑使用双指针的思想来判断,因此我们可以这样判断回文串了,因此我们就可以找到合适的定义dp数组的方法,我们就可以这样定义:布尔类型的dp[i][j]:表示区间范围[i,j] (注意是左闭右闭)的子串是否是回文子串,如果是dp[i][j]为true,否则为false。

       第二步确定递推公式,在确定递推公式时,就要分析如下几种情况。其实主要是两种情况,第一种情况当s[i]与s[j]不相等,那没啥好说的了,dp[i][j]一定是false。也就说明我们当前的字符串一定不是回文字符串,第二种情况大家需要仔细考虑就是s[i]与s[j]相等,首先第一种可能是下标i 与 j相同,同一个字符例如a,当然是回文子串,第二种可能是下标i 与 j相差为1,例如aa,也是回文子串,i 与 j相差大于1的时候,例如cabac,此时s[i]与s[j]已经相同了,我们看i到j区间是不是回文子串就看aba是不是回文就可以了,那么aba的区间就是 i+1 与 j-1区间,这个区间是不是回文就看dp[i + 1][j - 1]是否为true。以上所有的情况都必不可少。

      第三步就是初始化dp数组,dp[i][j]可以初始化为true么? 当然不行,怎能刚开始就全都匹配上了。因此我们需要把dp[i][j] = false才可以。

      第四步确定遍历顺序,这个有点意思,我们还是得看一下dp数组的示意图:

        因此我们如果这矩阵是从上到下,从左到右遍历,那么会用到没有计算过的dp[i + 1][j - 1],也就是根据不确定是不是回文的区间[i+1,j-1],来判断了[i,j]是不是回文,那结果一定是不对的。我们需要一定要从下到上,从左到右遍历,这样保证dp[i + 1][j - 1]都是经过计算的

        经过上述分析,我们就可以给出本题的解题代码:

class Solution {
public:int countSubstrings(string s) {//初始化dp数组vector<vector<bool>> dp(s.size(), vector<bool>(s.size(), false));//存储回文字串的个数int result = 0;//遍历顺序for (int i = s.size() - 1; i >= 0; --i){for (int j = i; j < s.size(); ++j){if (s[i] == s[j]){if (j - i <= 1) result++, dp[i][j] = true;else if (dp[i + 1][j - 1]) result++, dp[i][j] = true;}}}return result;}
};

        这道题其实有点反常规操作,当然理解遍历顺序与定义dp数组的思想是关键,我们这道题就分享到这里,我们继续我们的下一道题目。

第二题对应力扣编号为516的题目最长的回文子序列

       这道题与上一道题目应该是类似的,还是回文子串的问题,我们先看一下题目要求:

        我们应该是返回最长的回文子序列的长度,而且其实我们是可以对原字符串进行删除操作的,其实就是告诉我们我们找到的回文字符串未必是连续的,我们就使用动规五部曲来解决这道题目:

      第一步确定dp数组以及下标的含义,dp[i][j]:字符串s在[i, j]范围内最长的回文子序列的长度为dp[i][j]

      第二步是确定递推公式,在判断回文子串的题目中,关键逻辑就是看s[i]与s[j]是否相同。如果s[i]与s[j]相同,那么dp[i][j] = dp[i + 1][j - 1] + 2;这个很明显,如果s[i]与s[j]不相同,说明s[i]和s[j]的同时加入 并不能增加[i,j]区间回文子序列的长度,那么分别加入s[i]、s[j]看看哪一个可以组成最长的回文子序列。这个理解起来有点难度,大家应该记得上一道题目的思路,加入s[j]的回文子序列长度为dp[i + 1][j],加入s[i]的回文子序列长度为dp[i][j - 1]。那么dp[i][j]一定是取最大的,即:dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]),其实我们还是进行了删除操作,感觉与前面的题目思路都有相似的地方,理解dp数组的含义很重要。

      第三步是初始化dp数组,首先要考虑当i 和j 相同的情况,从递推公式:dp[i][j] = dp[i + 1][j - 1] + 2; 可以看出 递推公式是计算不到 i 和j相同时候的情况。其实我们需要考虑的是当i与j相同,那么dp[i][j]一定是等于1的,其他情况dp[i][j]初始为0就行,这样递推公式:dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]); 中dp[i][j]才不会被初始值覆盖。

      第四步就是确定遍历顺序,大家看下面的图: 

       我们就可以理解,所以遍历i的时候一定要从下到上遍历,这样才能保证下一行的数据是经过计算的

     综合上述分析我们就可以给出答案:

class Solution {
public:int longestPalindromeSubseq(string s) {//定义dp数组vector<vector<int>> dp(s.size(), vector<int>(s.size(), 0));//dp数组的初始化for (int i = 0; i < s.size(); ++i) dp[i][i] = 1;//确定遍历顺序for (int i = s.size() - 1; i >= 0; --i){for (int j = i + 1; j < s.size(); ++j){if (s[i] == s[j]) dp[i][j] = dp[i + 1][j - 1] + 2;else dp[i][j] = max(dp[i + 1][j],dp[i][j - 1]);}}return dp[0][s.size() - 1];}
};

动态规划总结篇

        到这里我们就完成了动态规划的所有题目,其实动态规划的题目类型很多,我们刷了不少类型,我们也深刻理解了动规五部曲在解题中的巧妙使用,如果遇到问题大家可以这样想:我们如果想不清楚dp数组的具体含义,递归公式从何谈起,甚至初始化的时候就写错了。如果看过背包系列,特别是完全背包,那么两层for循环先后顺序绝对可以搞懵很多人,反而递归公式是简单的。背包问题要注意区分,我们的遍历顺序很重要,希望大家可以好好努力,多去理解,掌握任何一种算法都不简单,更何况是动态规划这种比较难的题目,我们今天的分享就到这里,我们明天的单调栈见!

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

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

相关文章

如何发布npm包?

如何发布npm包&#xff1f; 1. 注册账号[npm官网](https://www.npmjs.com/)2. 检查 npm 源是否在官方 npm 仓库&#xff0c;如果不在&#xff0c;进行切换3. 检查4. 打包配置5. 发布6. 使用错误&#xff1a;版本更新命令 1. 注册账号npm官网 2. 检查 npm 源是否在官方 npm 仓库…

AI工具使用的最佳实践,如何通过AI工具提高创作与工作效率

随着科技的迅猛发展&#xff0c;人工智能&#xff08;AI&#xff09;已从遥不可及的未来构想&#xff0c;转变为广泛应用于各行业的实用工具。AI不仅在内容创作、设计、写作等领域展现出巨大潜力&#xff0c;还通过自动化和智能化显著提升了工作效率。本文将深入探讨如何通过选…

漏洞Reconfigure the affected application to avoid use of weak cipher suites. 修复方案

修复方案&#xff1a;禁用弱加密套件&#xff08;Weak Cipher Suites&#xff09; 1. 确认当前使用的加密套件 在修复前&#xff0c;先检查应用程序或服务器当前支持的加密套件&#xff1a; OpenSSL (适用于HTTPS/TLS服务)openssl ciphers -v ALL:COMPLEMENTOFALL | sortNgi…

AI对软件工程的影响及未来发展路径分析报告

目录 第一部分&#xff1a;引言 研究背景与意义 报告框架与方法论 第二部分&#xff1a;AI对不同行业软件工程的影响分析 数字化行业 制造业 零售业 工业领域 第三部分&#xff1a;大厂AI软件工程实践案例分析 微软 谷歌 阿里巴巴 华为 第四部分&#xff1a;未来…

WSL里执行python深度学习的一些方法记录

安装anaconda3&#xff1a; 可以直接从 Download Now | Anaconda 中下载&#xff0c;然后拷贝到WSL环境的某个目录&#xff0c;执行 bash xxxxxxx.sh 即可安装。 启动jupyter notebook&#xff1a; 先conda activate 当前环境&#xff0c;然后pip install jupyter 此时&am…

使用 SpyGlass Power Verify 解决方案中的规则

本节提供了关于使用 SpyGlass Power Verify 解决方案 的相关信息。内容组织如下: SpyGlass Power Verify 简介运行 SpyGlass Power Verify 解决方案在 SpyGlass Power Verify 解决方案中评估结果SpyGlass Power Verify 解决方案中的参数SpyGlass Power Verify 报告1 SpyGlass …

spring4第3课-ioc控制反转-详解依赖注入的4种方式

1&#xff0c;属性注入&#xff1b; 2&#xff0c;构造函数注入&#xff1b;(通过类型&#xff1b;通过索引&#xff1b;联合使用) 3&#xff0c;工厂方法注入&#xff1b;(非静态工厂&#xff0c;静态工厂) 4&#xff0c;泛型依赖注入&#xff1b;(Spring4 整合 Hibernate4…

使用Rust和并发实现一个高性能的彩色分形图案渲染

分形与 Mandelbrot Mandelbrot 集 (Mandelbrot Set) 是复数平面上一个点的集合,以数学家 Benot Mandelbrot 的名字命名。它是最著名的分形之一。一个复数 c 是否属于 Mandelbrot 集,取决于一个简单的迭代过程: z n + 1 = z n 2 + c z_{n+1}=z_{n}^2+c zn+1​=zn2​+c 如果…

微信小程序的软件测试用例编写指南及示例--性能测试用例

以下是针对微信小程序的性能测试用例补充,结合代码逻辑和实际使用场景,从加载性能、渲染性能、资源占用、交互流畅度等维度设计测试点,并标注对应的优化方向: 一、加载性能测试用例 测试项测试工具/方法测试步骤预期结果优化方向冷启动加载耗时微信开发者工具「性能」面板…

行为型:观察者模式

目录 1、核心思想 2、实现方式 2.1 模式结构 2.2 实现案例 3、优缺点分析 4、适用场景 5、注意事项 1、核心思想 目的&#xff1a;针对被观察对象与观察者对象之间一对多的依赖关系建立起一种行为自动触发机制&#xff0c;当被观察对象状态发生变化时主动对外发起广播&…

t009-线上代驾管理系统

项目演示地址 摘 要 使用旧方法对线上代驾管理系统的信息进行系统化管理已经不再让人们信赖了&#xff0c;把现在的网络信息技术运用在线上代驾管理系统的管理上面可以解决许多信息管理上面的难题&#xff0c;比如处理数据时间很长&#xff0c;数据存在错误不能及时纠正等问题…

LVS-NAT 负载均衡群集

目录 简介 一、LVS 与群集技术基础 1.1 群集技术概述 1.2 负载均衡群集的分层结构 1.3 负载均衡工作模式 二、LVS 虚拟服务器核心组件与配置 2.1 LVS 内核模块与管理工具 2.2 负载调度算法解析 2.3 ipvsadm 管理工具实战 三、NFS 共享存储服务配置 3.1 NFS 服务基础…

LLaMaFactory - 支持的模型和模板 常用命令

一、 环境准备 激活LLaMaFactory环境&#xff0c;进入LLaMaFactory目录 cd LLaMA-Factoryconda activate llamafactory 下载模型 #模型下载 from modelscope import snapshot_download model_dir snapshot_download(Qwen/Qwen2.5-0.5B-Instruct) 二、启动一个 Qwen3-0.6B…

EDW2025|数据治理的神话破除——从误区到现实

在当今数据驱动的世界中&#xff0c;数据治理已成为企业成功的关键因素。然而&#xff0c;许多组织在实施数据治理时&#xff0c;常常被一些常见的误区所困扰。本文将逐一破除这些误区&#xff0c;揭示数据治理的真实面貌。 误区一&#xff1a;你需要一个大的预算&#xff01;…

AIGC与影视制作:技术革命、产业重构与未来图景

文章目录 一、AIGC技术全景&#xff1a;从算法突破到产业赋能1. **技术底座&#xff1a;多模态大模型的进化路径**2. **核心算法&#xff1a;从生成对抗网络到扩散模型的迭代** 二、AIGC在影视制作全流程中的深度应用1. **剧本创作&#xff1a;从“灵感枯竭”到“创意井喷”**2…

ReactJS 中的 JSX工作原理

文章目录 前言✅ 1. JSX 是什么&#xff1f;&#x1f527; 2. 编译后的样子&#xff08;核心机制&#xff09;&#x1f9f1; 3. React.createElement 做了什么&#xff1f;&#x1f9e0; 4. JSX 与组件的关系&#x1f504; 5. JSX 到真实 DOM 的过程&#x1f4d8; 6. JSX 与 Fr…

Spring Advisor增强规则实现原理介绍

Spring Advisor增强规则实现原理介绍 一、什么是 Advisor&#xff1f;1. Advisor 的定义与本质接口定义&#xff1a; 2. Advisor 的核心作用统一封装切点与通知构建拦截器链的基础实现增强逻辑的灵活组合 二. Sprin当中的实现逻辑1 Advisor 接口定义2 PointcutAdvisor 接口定义…

小程序32-简易双向数据绑定

在WXML中&#xff0c;普通属性的绑定是单向的&#xff0c;例如:<input value"{{value}}" /> 如果希望用户输入数据的同时改变data中的数据&#xff0c;可以借助简易双向绑定机制。在对应属性之前添加model:前缀即可: 例如<input model:value"{{value}…

Nginx网站服务:从入门到LNMP架构实战

&#x1f3e1;作者主页&#xff1a;点击&#xff01; Nginx-从零开始的服务器之旅专栏&#xff1a;点击&#xff01; &#x1f427;Linux高级管理防护和群集专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2025年5月30日14点22分 前言 说起Web服务器&#xff0c…

【maker-pdf 文档文字识别(包含ocr),安装使用完整教程】

安装环境 conda create -n maker-pdf python3.12 conda activate marker-pdf pip install modelscope pip install marker-pdf -U下载模型 from modelscope import snapshot_downloadmodel_root "models" snapshot_download("Lixiang/marker-pdf", loca…