代码随想录27期|Python|Day52|​动态规划|​647. 回文子串|516. 最长回文子序列

news2024/9/23 17:22:14

 本文是动态规划的回文字符串部分。

647. 回文子串

本题需要搞清楚dp的定义、遍历顺序和递推公式。

1、dp数组的定义

由图片可知,不同于之前的dp数组直接定义为当前遍历到的位置处题目所要求得值,而是应该定义为i为开始,j为结束的子串是否是回文串

这是因为之前的遍历过程一般都是单向的,而回文串需要两遍同时进行扩展判断,所以不能够只保留遍历到“某一处”位置的回文串个数。

所以,dp的定义发生了改变,定义一个子序列是否是回文串。

2、递推公式

随着dp定义发生的变化,递推公式也需要进行修改。

具体来讲包括:结果个数的更新、向两侧扩展子串是否是回文串的判断。

2.1当前i和j所指向的字符相等

(1)如果只有一个元素,也就是j-i=1,那么肯定这个单一的字符是回文串;此时res += 1,同时需要把此处的dp[i][j] = True标记为回文串。

后来发现,其实此处的单个字符就是最小的回文串单元,它们构成了其余回文串判断的基础

(2)如果有2个以上的元素,此时就需要进行判断了。

判断的依据是依靠上一个状态,也就是dp[i+1][j-1],也就是在[i, j]这个区间内分别往内收缩一个索引的区间。

如果这个收缩的区间是True(回文串),那么[i, j]区间肯定也是回文串。此时res += 1,并把dp[i][j] = True。

2.2当前i和j所指向的字符不相等

如果不相等的话这个区间就会被设置为False。实际上在初始化的时候已经全部置为Fasle了,所以不需要再进行操作。

3、初始化

初始化其实是根据定义来的,定义为判断i,j是回文子串后设置为True,那么初始化全部置为False即可,表示全部都不是回文串。

4、遍历顺序

遍历顺序由递推公式确定。

在递推公式中,除了直接对s中字符的比较之外,还需要依靠dp[i+1][j-1]来进行更新,可以看到这个dp的位置在当前位置的左下方

那么,遍历的顺序就相应地i从大到小(从下往上)、j从小到大(从左往右)

class Solution(object):
    def countSubstrings(self, s):
        """
        :type s: str
        :rtype: int
        """
        dp = [[False] * len(s) for _ in range(len(s))]
        res = 0
        for i in range(len(s)-1, -1, -1):
            for j in range(i, len(s)):
                if s[i] == s[j]:
                    if j - i <= 1:
                        dp[i][j] = True
                        res += 1
                    elif dp[i+1][j-1] == True:
                        dp[i][j] = True
                        res += 1
        return res

本题和之前题目的根本区别在于dp数组的定义需要根据回文串判断的依据,同时向两边扩展,这决定了dp没法直接设置为题目所要求的个数,而是表征区间是否是回文串。

双指针解法

双指针解法主要是在遍历的是否分别以当前单个字符和两个字符为中心向左右延伸,统计满足条件的情况。

class Solution(object):
    def countSubstrings(self, s):
        """
        :type s: str
        :rtype: int
        """
        # 双指针
        res = 0
        for i in range(len(s)):
            res += self.extend(s, i, i, len(s))  # 单个字符作为中心向两边延伸
            res += self.extend(s, i, i+1, len(s))  # 两个字符作为中心向两边延伸
        return res

    def extend(self, s, i, j ,length):
        res = 0
        # 如果当前字符串满足回文串的要求,且区间首位在整个字符串内
        while i >= 0 and j < length and s[i] == s[j]:
            i -= 1  # 向左扩张
            j += 1  # 向右扩张
            res += 1  # 结果增加1
        return res

516. 最长回文子序列

本题在原来的基础上加上了自由删减的能力,所以在进行更新的时候会有所区别,和之前做的编辑距离类的更新方式类似。

1、dp定义

dp[i][j]定义为在i,j区间内的最长回文子串的长度,注意,这里是“包含”回文子串,和上一题的要求“必须以i和j为边界”不同

2、dp更新

对于dp的更新分为两个方面:

(1)s[i] == s[j],此时相当于当前满足回文子串的要求,由于可以删除不要的元素,所以只要两个字符相等,就可以在原来dp数组的基础上+2

(2)字符不相等时,分为两种情况:

<1>i索引向内收缩,变为i+1,j索引hold住不变(编辑距离的处理方式),此时dp[i][j] = dp[i+1][j];

<2>j索引向内收缩,变为j-1,i索引hold住不变(也是编辑距离的方式),此时dp[i][j] = dp[i][j-1]

综上,当字符不相等的时候,dp[i][j] = max(dp[i+1][j], dp[i][j-1]),相当于保持两个边界分别向内收缩后的最大值。

3、初始化

由于单个字符自身就算是最小的字符串单位(上一题的结论),所以初始化就是对角线元素全部设置为1(i=j的时候)。

4、遍历顺序

从图上和2、中的更新所用到的索引位置来看,dp更新需要左边、下边、左下方向的dp数组来更新,所以依然是外层i从大到小,内层j从小到大

class Solution(object):
    def longestPalindromeSubseq(self, s):
        """
        :type s: str
        :rtype: int
        """
        dp = [[0] * len(s) for _ in range(len(s))]
        for i in range(len(s)):
            dp[i][i] = 1

        for i in range(len(s)-1, -1, -1):
            for j in range(i + 1, len(s)):
                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][-1]

Day52完结!!!

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

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

相关文章

探索音视频SDK的双重核心:客户端与服务端的协同作用

在当今的数字化时代&#xff0c;音视频技术已成为连接人与人、人与世界的重要桥梁。从社交娱乐到在线教育&#xff0c;从远程医疗到视频会议&#xff0c;音视频技术的应用无处不在&#xff0c;极大地丰富了我们的生活方式和工作模式。本文将深入探讨音视频SDK的两大核心类别——…

横版闯关手游【全明星时空阿拉德】Linux手工服务端+运营后台+双app端

横版闯关手游【时空阿拉德】&#xff08;【全明星阿拉德】&#xff09;阿拉德系列2022整理Linux手工服务端余额充值后台安卓苹果双端。 运营后台看目录结构是thinkphp开发的。 代码免费下载&#xff1a;百度网盘

DNAT和SNAT实践

NAT分SNAT和DNAT两种。从名字上区分&#xff1a; SNAT将源IP地址替换为出口网络的IP地址&#xff0c;以便内网地址可以访问外网服务。一般受限于公网IP有限&#xff0c;一个内网集合想访问外网服务&#xff0c;则用统一的出口做代理。出口配置公网IP&#xff0c;帮助从此发出的…

Java重修笔记 第五十四天 坦克大战(二)常用的绘图方法、画出坦克图形

常用的绘图方法 1.设置当前画笔的颜色&#xff0c;可多次调用 public abstract void setColor(Color c) 参数&#xff1a;c -颜色 2. 画一条直线 public abstract void drawLine(int x1, int y1, int x2, int y2) 参数&#xff1a;x1 - 第一个点的 x坐标。 y1 - 第一点的 y坐…

Git使用—把当前仓库的一个分支push到另一个仓库的指定分支、基于当前仓库创建另一个仓库的分支并推送到对应仓库(mit6828)

目录 背景提示 将当前仓库的一个分支push到另一个仓库的指定分支 直接基于仓库rep1中的某个分支创建新的分支并将其推送到目标仓库rep2 补充 参考链接 背景提示 最近打算做一下mit6.828的项目&#xff0c;这个仓库使用问题困扰了自己一段时间&#xff0c;由于6828官方提供…

92、K8s之ingress下集

一、ingress 1.1、两种部署方式 1、ingress------------deployment nodeport ​ daemonset hostnetwork----每台设备只能有一个pod&#xff0c;因为直接使用宿主机的端口&#xff0c;所以只能开启一个pod。 2、ingress------svc------deployment里面的pod&#xff0c;这种…

文件IO编程

文章目录 文件描述符相关系统调用文件有关的系统调用文件操作函数--creat函数文件操作函数--open函数文件操作函数--read函数文件操作函数--write函数文件操作函数--close函数文件操作函数--lseek函数缓冲区的大小对性能的影响 实验&#xff1a;调用系统函数&#xff0c;实现文…

Linux:体系结构和操作系统管理

目录 一、冯诺依曼体系结构 1.问题1 2.问题2 二、操作系统管理 一、冯诺依曼体系结构 本章将会谈论一下对冯诺依曼计算机体系结构的理解。 在2024年&#xff0c;几乎所有的计算机&#xff0c;都遵守冯诺依曼体系结构。 冯诺依曼体系结构是应用在硬件层面的&#xff0c;而硬…

Docker高级管理--Compose容器编排与私有仓库(Docker技术集群与应用)

本文介绍了Docker的三大工具&#xff1a;Docker Machine用于创建和管理Docker主机&#xff0c;Docker Compose用于单引擎模式下的多容器应用部署和管理&#xff0c;而Docker Swarm则是一个集群管理工具&#xff0c;提供微服务应用编排功能。Docker Machine支持在不同环境配置Do…

【代码随想录训练营第42期 Day56打卡 - 图论Part6 - 并查集2 - 冗余连接问题

目录 一、做题心得 二、题目与题解 题目一&#xff1a;108. 冗余连接 题目链接 题解&#xff1a;并查集 题目二&#xff1a;109. 冗余连接II 题目链接 题解&#xff1a;并查集 三、小结 一、做题心得 冗杂连接问题是图论章节应用并查集的经典问题。所有的顶点通过边相…

Redis 篇- 实战项目中使用 Redis 实现经典功能(异步秒杀商品、点赞功能、共同关注的好友、投喂功能)

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 使用 Redis 实现异步秒杀 1.1 基于 Lua 脚本判断是否符合条件&#xff1a;库存是否充足、一人一单 1.2 基于 Redis 中的 Stream 实现消息队列 1.3 使用 Java 操作…

Unity Hub自动安装指定版本Unity的Android开发环境

Unity开发Android环境要求SDK、DNK、JDK、Gradle版本都要对才能发布APK&#xff0c;自己去配置很容易出错。Unity Hub可以自动安装指定版本Unity的Android开发环境。 1.安装国内用的UnityHub&#xff08;我这里用的3.3.2-c6&#xff09; 2.找到对应的Unity版本 3.点击【从Unit…

docker管理redis集群

1.拉取redis镜像 docker pull redis拉取完成 [rootlocalhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE redis latest a617c1c92774 3 years ago 105MB2.运行redis容器 docker run -itd --name redis-test01 -p 6379:6379…

谈谈PCIe VID、DID、SSID、SSVID背后的智慧

PCIe Vendor ID 想了半天还是觉得从“ID是什么”这个问题开始比较好。那么ID是什么&#xff1f;ID就是身份。那身份又是什么&#xff1f;身份就是一个合理存在&#xff0c;用于区分不同个体。为什么叫“合理存在”呢&#xff1f;如果国家不给你发身份证&#xff0c;你就是黑户…

记一次导入dbf文件后数据为空问题的解决方法

前言 省流&#xff1a;这篇文章最终采用的是更换导出文件格式的方法&#xff0c;看到这里觉得方法不适用的小伙伴可以不用浪费几秒钟看完这篇文章哦。 问题描述 作者使用的是Navicat数据库管理工具&#xff0c;然后在将源数据库的数据表导出为dbf格式文件后&#xff0c;再将…

F110批量付款如何Debug BTE增强(后台JOB的调试方法)

F110批量付款如何Debug BTE增强&#xff08;后台JOB的调试方法&#xff09; SAP系统中的F110&#xff08;Automatic Payment&#xff09;是一个常用的付款程序&#xff0c;在实施过程中&#xff0c;也经常会遇到一些运行的错误&#xff0c;而对于此类的错误&#xff0c;通常的…

基于SpringBoot的租房网站系统

你好呀&#xff0c;我是计算机学姐码农小野&#xff01;如果有相关需求&#xff0c;可以私信联系我。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot框架 工具&#xff1a;ECLIPSE 系统展示 首页 管理员功能界面 用户信息界面 预约看房界…

动手学深度学习(pytorch)学习记录28-使用块的网络(VGG)[学习记录]

目录 VGG块VGG网络训练模型 VGG块 定义了一个名为vgg_block的函数来实现一个VGG块 import torch from torch import nn from d2l import torch as d2ldef vgg_block(num_convs, in_channels, out_channels):layers []for _ in range(num_convs):layers.append(nn.Conv2d(in_…

线程池原理及改造

目录 一 线程池执行原理 二 线程池改造(一) 三 线程池改造(二) 一 线程池执行原理 首先我们先了解一下线程池里面几个参数&#xff1a; 第一个是核心线程数&#xff0c;第二个是线程池最大线程数。&#xff08;线程池里面的线程分为核心线程和非核心线程&#xff0c;既然核心…

人物化身持有者每月奖励:九月版

世界急需英雄。你准备好响应号召了吗&#xff1f; 穿上你的斗篷&#xff0c;戴上你的面具&#xff0c;用你的风格保卫 The Sandbox 的街道吧&#xff01;本月为人物化身持有者准备的独家奖励是 The Sandbox 超级套装&#xff01; 本月我们将首次向我们生态系统中的所有人物化…