代码随想录算法训练营Day57|647. 回文子串、516.最长回文子序列、动态规划总结

news2024/11/30 6:36:47

目录

647. 回文子串

前言

思路

算法实现 

516.最长回文子序列

前言

思路

算法实现 

动态规划总结

动规五部曲回顾

动规各小专题问题


647. 回文子串

题目链接

文章链接

前言

        本题利用动态规划求解时,dp数组的定义与前面的就有些不同了,是难点之一。

思路

         本题利用动态规划的方法进行求解:

1.确定dp数组及其下标的含义:

        如果按照前面做题的思路将dp数组的定义设置为dp[i] 为 下标i结尾的字符串有 dp[i]个回文串的话,很难找到递推关系。

        因此本题要根据回文子串的性质来确定dp数组:        

         在判断字符串s是否回文时,只要知道s[1],s[2],s[3] 这个子串是回文的,那么只需要比较 s[0]和s[4]这两个元素是否相同,如果相同的话,这个字符串s 就是回文串。

        此时就找到了一种递归关系,也就是判断一个子字符串(字符串的下表范围[i,j])是否回文,依赖于,子字符串(下表范围[i + 1, j - 1])) 是否是回文。

        所以为了明确这种递归关系,我们的dp数组是要定义成一位二维dp数组。

        布尔类型的dp[i][j]:表示区间范围[i,j] (左闭右闭)的子串是否是回文子串,如果是dp[i][j]为true,否则为false。

2.确定递推公式

        整体上是两种情况,就是s[i]与s[j]相等,s[i]与s[j]不相等这两种。

        s[i]与s[j]不相等时,dp[i][j]就是false;

        s[i]与s[j]相等时,又分为三种情况:

        情况一:下标i与j相同时,此时为同一个字符,必然是回文子串;

        情况二:下标i与j相邻时,此时也是回文子串;

        情况三:下标i与j不相邻时,要看是s[i]之后和s[j]之前的部分是否是回文子串,若是则算上s[i]、s[j]也为回文子串;

        在每种情况中对应统计回文子串的数目result;

3.初始化dp数组:

        一开始将dp[i][j]全部初始化为false,否则对后面的判断是否为回文子串有影响;

4.确定遍历顺序:

        首先从递推公式中可以看出,情况三是根据dp[i + 1][j - 1]是否为true,在对dp[i][j]进行赋值true的。dp[i + 1][j - 1] 在 dp[i][j]的左下角,如图:

        

        遍历顺序是从左到右,从下到上。

5.打印dp数组:

        举例,输入:"aaa",dp[i][j]状态如下:

         

        图中有6个true,所以就是有6个回文子串。

算法实现 

class Solution {
public:
    int countSubstrings(string s) {
        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) {
                        dp[i][j] = true;
                        result++;
                    }
                    else if (dp[i + 1][j - 1] == true) {
                        dp[i][j] = true;
                        result++;
                    }
                }
            }
        }
        return result;
    }
};

516.最长回文子序列

题目链接

文章链接

前言

         上一题要求的是连续的回文子串,本题求最长回文子序列就没有了连续的要求。

思路

        依然是利用动规五部曲进行分析:

1.确定dp数组及其下标的含义:

        dp[i][j]:字符串s在下标在[i, j]范围内的最长回文子串长度为dp[i][j];

2.确定递推公式:

        还是分s[i]和s[j]相等和不等两种情况进行讨论:

        当s[i]和s[j]相等时,回文子序列长度加2,dp[i][j] = dp[i + 1][j - 1] + 2;

        当s[i]和s[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]);

3.初始化dp数组:

        从递推公式: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]才不会被初始值覆盖。

4.确定遍历顺序:

        从递归公式中,可以看出,dp[i][j] 依赖于 dp[i + 1][j - 1] ,dp[i + 1][j] 和 dp[i][j - 1]:

        

         所以遍历顺序为从下到上,从左到右;

5.打印dp数组:

        输入s:"cbbd" 为例,dp数组状态如图:

        

        dp[0][s.size() - 1]; 为最终结果。 

算法实现 

class Solution {
public:
    int longestPalindromeSubseq(string s) {
        vector<vector<int>> dp(s.size(), vector<int> (s.size(), 0));
        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];
    }
};

动态规划总结

动规五部曲回顾

        1.确定dp数组及其下标含义;

        2.确定递推公式;

        3.初始化dp数组;

        4.确定遍历顺序;

        5.打印dp数组;

动规各小专题问题

        背包问题;

        打家劫舍;

        股票系列;

        子序列系列;

        各部分题目都有较强的技巧性,需要反复训练总结。

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

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

相关文章

Python算法题集_翻转二叉树

Python算法题集_翻转二叉树 题226&#xff1a;翻转二叉树1. 示例说明2. 题目解析- 题意分解- 优化思路- 测量工具 3. 代码展开1) 标准求解【DFS递归】2) 改进版一【BFS迭代&#xff0c;节点循环】3) 改进版二【BFS迭代&#xff0c;列表循环】 4. 最优算法 本文为Python算法题集…

黄金交易策略(Nerve Nnife.mql4):利用锁定单消除保留单

完整EA&#xff1a; Nerve Knife.ex4黄金交易策略_黄金趋势ea-CSDN博客 趋势突然转变有大约30%的概率会产生一张锁定单&#xff0c;反复转变之后难免就会形成几个保留单了&#xff0c;可以选择一张与保留单同向同大小&#xff08;接近也行&#xff09;的单&#xff0c;去消除这…

详解Python中的str.format方法

字符串的内置方法大致有40来个&#xff0c;但是一些常用的其实就那么20几个&#xff0c;而且里面还有类似的用法&#xff0c;区分度高比如&#xff1a;isalpha,isalnum,isdigit&#xff0c;还有一些无时不刻都会用到的split切分&#xff0c;join拼接&#xff0c;strip首尾去指定…

深度学习:Pytorch安装的torch与torchvision的cuda版本冲突问题与解决历程记录

今天不小心将conda环境中的一个pytorch环境中的torch包给搞混了&#xff0c;将其更新了一下&#xff0c;发生了一些问题&#xff1a; 当时运行了一下这个代码&#xff1a; pip install torchvision --upgrade 导致了环境中包的混乱&#xff1a; 只能说欲哭无泪&#xff0c;当…

代码随想录day21--回溯基础

理论基础 回溯法也可以叫回溯搜索法&#xff0c;它是一种搜索的方式。我们在二叉树中也多次提到了回溯。回溯是递归的副产品&#xff0c;只要使用了递归就会有回溯&#xff0c;我们我们就可以笼统的将回溯函数称为递归函数 回溯法解决的问题 1.组合问题&#xff1a;N个数里面…

IMX6ULL移植U-Boot 2022.04

目录 目录 1.编译环境以及uboot版本 2.默认编译测试 3.uboot中新增自己的开发板 3.编译测试 4.烧录测试 5.patch文件 1.编译环境以及uboot版本 宿主机Debian12u-boot版本lf_v2022.04 ; git 连接GitHub - nxp-imx/uboot-imx: i.MX U-Boot交叉编译工具gcc-arm-10.3-2021.0…

《剑指Offer》笔记题解思路技巧优化 Java版本——新版leetcode_Part_2

《剑指Offer》笔记&题解&思路&技巧&优化_Part_2 &#x1f60d;&#x1f60d;&#x1f60d; 相知&#x1f64c;&#x1f64c;&#x1f64c; 相识&#x1f353;&#x1f353;&#x1f353;广度优先搜索BFS&#x1f353;&#x1f353;&#x1f353;深度优先搜索DF…

esp8266-01s WIFI模块使用(一)- AT指令

时间记录&#xff1a;2024/2/15 一、注意事项 &#xff08;1&#xff09;使用英文双引号表示字符串数据 &#xff08;2&#xff09;默认波特率115200 &#xff08;3&#xff09;AT指令以“\r\n”结尾 &#xff08;4&#xff09;3.3V电源接口先连接单片机的3.3V&#xff0c;如…

Spring 用法学习总结(二)之基于注解注入属性

Spring学习 5 基于注解方式创建对象6 基于注解注入属性 5 基于注解方式创建对象 注解是代码的特殊标记&#xff0c;可以简化xml配置&#xff0c;格式&#xff1a;注解名称(属性名称属性值&#xff09;&#xff0c;可以作用在类、方法、属性上 以下注解都可以创建bean实例 Com…

VS Code中的JDK设置

在VS Code使用中&#xff0c;如果机器只安装了一个版本的JDK版本&#xff0c;一般不需要特别关注JDK 的配置&#xff0c;但是在以下状况下&#xff0c;需要对JDK进行特别的配置&#xff1a; 机器有多个JDK版本&#xff0c;不同的项目使用不同的JDK版本项目使用的JDK版本较低&a…

【web | CTF】BUUCTF [护网杯 2018] easy_tornado

天命&#xff1a;这题是框架性的漏洞&#xff0c;Python的web服务器框架&#xff0c;应该已经比较古老了 开局先看一下三个文件 简单阅读后会发现&#xff0c;这里存在文件包含漏洞&#xff0c;可以直接读取文件&#xff0c;但是有一个哈希值校验 一开始我以为是扫描文件后得到…

vue3 之 商城项目—支付

支付模版 pay/index.vue <script setup> const payInfo {} </script> <template><div class"xtx-pay-page"><div class"container"><!-- 付款信息 --><div class"pay-info"><span class"ic…

腾讯云4核8G服务器够用吗?能支持多少人?

腾讯云4核8G服务器支持多少人在线访问&#xff1f;支持25人同时访问。实际上程序效率不同支持人数在线人数不同&#xff0c;公网带宽也是影响4核8G服务器并发数的一大因素&#xff0c;假设公网带宽太小&#xff0c;流量直接卡在入口&#xff0c;4核8G配置的CPU内存也会造成计算…

Linux实用指令

Linux实用指令 1.指定运行级别 运行级别说明&#xff1a; 0 &#xff1a;关机 1 &#xff1a;单用户【找回丢失密码】 2&#xff1a;多用户状态没有网络服务 3&#xff1a;多用户状态有网络服务 4&#xff1a;系统未使用保留给用户 5&#xff1a;图形界面 6&#xff1a;系统重…

山西电力市场日前价格预测【2024-02-11】

日前价格预测 预测说明&#xff1a; 如上图所示&#xff0c;预测明日&#xff08;2024-02-11&#xff09;山西电力市场全天平均日前电价为121.99元/MWh。其中&#xff0c;最高日前电价为475.98元/MWh&#xff0c;预计出现在19:00。最低日前电价为0.00元/MWh&#xff0c;预计出…

姿态传感器MPU6050模块的基本使用总结

以下两篇文章可作为参考&#xff1a; 姿态传感器MPU6050原理及应用超详细讲解 - 采芯网 基于STM32的四旋翼无人机项目&#xff08;二&#xff09;&#xff1a;MPU6050姿态解算&#xff08;含上位机3D姿态显示教学&#xff09;-CSDN博客 基本介绍 随着科技的发展&#xff0c;我们…

Write operation failed: computed value is readonly问题解决

源代码&#xff1a; // 封装倒计时逻辑函数 import { computed, ref } from vue import dayjs from dayjs export const useCountDown () > {// 1.响应式数据const time ref(0)// 格式化时间const formatTime computed(()>dayjs.unix(time.value).format(mm分ss秒))/…

表的连接

目录 内连接实现效果 使用左外连接&#xff0c;将所有的员工信息都显示出来&#xff0c;即便他没有对应的部门 使用右外连接&#xff0c;将所有的部门信息都显示出来 查询每个员工的编号、姓名、职位&#xff0c;以及所在各部门的领导姓名、领导职位 确定所需要的数据表 确…

了解Ping、Wget、端口、Netstat和Curl命令

1. 端口 1.1 什么是端口&#xff1f; 端口是一种用于标识不同应用程序或服务的逻辑通道。它是一个数字&#xff0c;取值范围从0到65535。常见的端口有一些已经被标准化&#xff0c;比如HTTP使用的80端口&#xff0c;HTTPS使用的443端口。 1.2 了解端口状态 使用netstat -an…