leetcode-647-回文子串

题意描述:

给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。

回文字符串 是正着读和倒过来读一样的字符串。

子字符串 是字符串中的由连续字符组成的一个序列。

具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。

示例:

输入:s = “abc”
输出:3
解释:三个回文子串: “a”, “b”, “c”

输入:s = “aaa”
输出:6
解释:6个回文子串: “a”, “a”, “a”, “aa”, “aa”, “aaa”


提示:

1 <= s.length <= 1000
s 由小写英文字母组成

解题思路:
Alice: 看 s 的长度有点小啊,最多也就是 1000 * 999 / 2 种,一个一个去试,估计也不会超时的。
Bob: 嘿,暴力解果然没超时。
Alice: 这题是动态规划吗 ?老是认不出来到底是什么题目。
Bob: 看起来像,回文字符串这种东西不都是前后之间有关系的吗 ?
Alice: 假设有个二维数组 dp,dp[i][j] 表示这个子字符串是不是回文串,递推关系是啥呢 ?
Bob: dp[i][j] = dp[ i + 1][j - 1] && s[i-1] === s[j+1],然后 i-1, j+1 越界的情况要单独求解。
Alice: 具体的求解方式呢 ?
Bob: 先把二维数组的第一行求出来,然后求解数组的右上部分就行了。
Alice: 等一下,你的递推公式里面,为啥是 i + 1j - 1 ?
Bob: 因为 dp[i][j] 表示的是子字符串 s.slice(i, j+1) 是不是回文,i 一定是要小于 j 的,而根据回文的规则,应该是从两端向中间靠拢,也就是 i+1j-1 了。
Alice: 那你的递推规则能覆盖 abba 这种情况吗 ?
Bob: 可以的,这种情况 dp[1][2] = dp[2][1] ... 就属于特殊情况,要单独求解的
Alice: 好像有问题啊,"sfffsfafsffsf" 这个 case 没过
Bob: 是不是二维数组的计算方式不对,这里的计算方向要注意一下,计算 dp[i][j] 要先求出 dp[i+1] 的,也就是应该按照从下到上的顺序求解二维数组的右上部分。
Alice: 原来如此,还有一个问题什么是 i-1, j+1 越界的情况呢 ?
Bob: 也就那几个条件,最小,最大, 左边和右边的大小关系
Alice: 通过了!!


Bob: 我看到好像还有一种双指针的解法,好像更快 ?
Alice: 双指针 ?双指针不行吧 ?怎么处理奇数个的回文串和偶数个的回文串呢 ?双指针从哪里开始,到哪里结束呢 ?
Bob: 如果双指针可以的话,肯定是两个指针,一个往左一个往右,让回文串越来越长,这样才能利用回文的特点。
Alice: 那就是从每个字符开始,向两边扩张?那偶数个的回文串呢 ?一个中心位置能确定一组回文串吗 ?
Bob: 我明白了,双指针扩张的过程中应该总是左右同时增加两个字符,这样的话。
Alice: 这样的话,奇数个的和偶数个的回文串是一样的,只是初始化的时候奇数个的两个指针位置一样,偶数个的两个指针位置是 ii + 1
Bob: 对哦,假设有一个根据双指针的起始位置,计算向两边扩张的过程中的回文字符串。只需要在遍历字符串的时候调用两次这个函数就行了。
Alice: 是的,func(i, i)func(i, i+1)
Bob: 牛啊牛啊


代码:

typescript 暴力

function countSubstrings(s: string): number {const chars = s.split('');const isHuiwen = (startIdx: number, endIdx: number) => {while(endIdx >= startIdx && chars[startIdx] === chars[endIdx]) {endIdx--;startIdx++;}return endIdx < startIdx;}let result = chars.length;for(let len=2; len<=chars.length; len += 1) {for(let i=0; i<chars.length; i++){const j = i + len - 1;if (j > chars.length) {break;}result  += isHuiwen(i, j) ? 1 : 0;}}return result;
};

动态规划 typescript

function countSubstrings(s: string): number {const charList = s.split('');const total = charList.length;const isHuiwen =  (startIdx: number, endIdx: number) => {while(endIdx >= startIdx && charList[startIdx] === charList[endIdx]) {endIdx--;startIdx++;}return startIdx > endIdx;}const isLegalStartEnd = (start: number, end: number) => {return start <= end && start >= 0 && end < total;}const dp = new Array(total);for(let i=0; i<total; ++i) {dp[i] = new Array(total).fill(false);}let result = 1;dp[total-1][total-1] = true;for(let start=total-2; start>=0; start-= 1){for(let end=start; end<total; end+= 1){const ss = start + 1;const ee = end - 1; dp[start][end] =  isLegalStartEnd(ss, ee) ? dp[ss][ee] && charList[start] === charList[end] : isHuiwen(start, end);result += dp[start][end] ? 1 : 0;}}return result;
};

typescript 双指针

function countSubstrings(s: string): number {const charList = s.split('');const total = charList.length;const getPartialResult = (left: number, right: number) => {let partialResult = 0;while(left >=0 && right < total && charList[left] === charList[right]){partialResult += 1;left--;right++;}return partialResult;}let result = 0;for(let i=0; i<total; i++){result += getPartialResult(i, i);result += getPartialResult(i, i+ 1);}return result;
};

提示

  1. js 中初始化二维数组的方法,不要使用 new Array(len).fill( new Array(len).fill(0) )
    这种方式,这种方式 fill 进去的 Array 是同一个数组,并不是一个真实的二维数组。

参考:

  • 题目链接

箴言

《黑客帝国》(The Matrix):
“真正重要的东西,是无法被眼睛看到的。” - 摩洛菲斯(Morpheus)

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

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

相关文章

论文笔记--Skip-Thought Vectors

论文笔记--Skip-Thought Vectors 1. 文章简介2. 文章概括3 文章重点技术3.1 Skip Thought Vectors3.2 词表拓展 4. 文章亮点5. 原文传送门6. References 1. 文章简介 标题&#xff1a;Skip-Thought Vectors作者&#xff1a;Ryan Kiros, Yukun Zhu, Ruslan Salakhutdinov, Rich…

JavaSE复盘2

Collection接口的接口对象集合&#xff08;单列集合&#xff09; List接口&#xff1a;元素按照先后有序保存&#xff0c;可重复 LinkList接口实现类&#xff0c;链表&#xff0c;随机访问&#xff0c;没有同步&#xff0c;线程不安全ArrayList接口实现类&#xff0c;数组&…

element时间选择器的默认值

概览&#xff1a;vue使用element组件&#xff0c;需要给时间选择器设置默认值&#xff0c;场景一&#xff1a;默认时间选择器&#xff0c;场景二&#xff1a;时间范围选择器&#xff0c;开始时间和结束时间。 一、默认时间选择器 实现思路&#xff1a; element组件的v-model绑…

“深入探究Spring Boot:从入门到精通“

标题&#xff1a;深入探究Spring Boot&#xff1a;从入门到精通 摘要&#xff1a;本文将介绍Spring Boot框架的基本概念和特点&#xff0c;以及详细讲解如何使用Spring Boot进行快速开发。通过深入学习Spring Boot的各个方面&#xff0c;读者将能够全面掌握这个强大的开发框架…

忘记安卓图案/密码锁如何解锁?

如何解锁Android手机图案锁&#xff1f;如何删除忘记的密码&#xff1f;Android 手机锁定后如何重置&#xff1f;这是许多智能手机用户在网上提出的几个问题。为了回答这些问题&#xff0c;我们想出了一些简单有效的方法来解锁任何设备而不丢失数据。 忘记手机密码可能会令人恐…

Git基础入门

git基础入门 Git是一款免费、开源的分布式 版本控制系统 &#xff0c;用于敏捷高效地处理任何或小或大的项目。 Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。 git的安装 下载地址 注意&#xff1a; 不要安装在中文目录不要使用桌…

web服务器(Tomcat)

目录 一、web服务器 1. 常见web服务器 2. web服务器简介 二、 Apache Tomcat服务器 1. Tomcat服务器简介 2. Tomcat服务器基本使用 3. 启动tomcat常见问题 &#xff08;1&#xff09;启动tomcat控制台乱码 &#xff08;2&#xff09;启动tomcat闪退问题 &#xff08;…

DevOps系列文章 之 Springboot单元测试

在没有代码生成工具或尝试一门新的 ORM框架时&#xff0c;当我们希望不去另外写 Service 和 Controller 来验证 DAO 层的代码不希望只通过接口请求的方式来验证时&#xff0c;这时候单元测试的方式就可以帮助我们满足这一需求。 在我们开发Web应用时&#xff0c;经常会直接去观…

爬虫003_pycharm的安装以及使用_以及python脚本模版设置---python工作笔记021

这里我们用ide,pycharm来编码,看一看如何下载 这里我们下载这个社区办,这个是免费的,个人版是收费的 然后勾选以后 安装以后我们来创建一个项目 这里可以选择python的解释器,选择右边的... 这里我们找到我们自己安装的python解释器

Android Hook系统 Handler 消息实现

前言 主线程的Handler 主要依赖于 ActivityThread&#xff0c;Android是消息驱动&#xff0c;比如view的刷新&#xff0c;activity的创建等&#xff0c;如果能打印系统层Handler消息日志&#xff0c;就需要对于系统层的Handler 进行Hook 原理 ActivityThread中 mH对象主要负责…

【雕爷学编程】MicroPython动手做(02)——尝试搭建K210开发板的IDE环境4

7、使用串口工具 &#xff08;1&#xff09;连接硬件 连接 Type C 线&#xff0c; 一端电脑一端开发板 查看设备是否已经正确识别&#xff1a; 在 Windows 下可以打开设备管理器来查看 如果没有发现设备&#xff0c; 需要确认有没有装驱动以及接触是否良好 &#xff08;2&a…

【JVM】详解JVM的五大内存模型、可能出现的异常以及堆栈引用易错点

文章目录 1、堆(线程共享)2、方法区(线程共享)3、虚拟机栈&#xff08;线程私有&#xff09;4、本地方法栈(线程私有)5、程序计数器(线程私有)6、易错点 源自&#xff1a;深入理解Java虚拟机&#xff1a;JVM高级特性与最佳实践&#xff08;第3版&#xff09; 周志明 1、堆(线程…

C语言第十一课--------操作符的使用与分类-------基本操作

作者前言 作者介绍&#xff1a; 作者id&#xff1a;老秦包你会&#xff0c; 简单介绍&#xff1a; 喜欢学习C语言和python等编程语言&#xff0c;是一位爱分享的博主&#xff0c;有兴趣的小可爱可以来互讨 个人主页::小小页面 gitee页面:秦大大 一个爱分享的小博主 欢迎小可爱们…

css 书写规范!其他人总结!

CSS书写顺序 1.位置属性(position, top, right, z-index, display, float等) 2.大小(width, height, padding, margin) 3.文字系列(font, line-height, letter-spacing, color- text-align等) 4.背景(background, border等) 5.其他(animation, transition等) CSS书写规范 使用…

MyBatis-Plus自定义sql注入器

文章目录 一、前言二、MyBatis-Plus自定义sql注入器功能实现2.1、编写自定义sql类2.2、将自定义sql添加到BaseMapper中2.3、编写自己的sql注入器 一、前言 在日常开发过程中&#xff0c;我们可能会发现 MyBatis-Plus 提供的那些自带的 sql 语句无法满足我们的开发需求&#xf…

web自动化测试进阶篇05 ——— 界面交互场景测试

&#x1f60f;作者简介&#xff1a;博主是一位测试管理者&#xff0c;同时也是一名对外企业兼职讲师。 &#x1f4e1;主页地址&#xff1a;【Austin_zhai】 &#x1f646;目的与景愿&#xff1a;旨在于能帮助更多的测试行业人员提升软硬技能&#xff0c;分享行业相关最新信息。…

【Ajax】笔记-同源策略

同源策略(Same-Origin Policy)&#xff0c;是浏览器的一种安全策略 同源&#xff08;即url相同&#xff09;&#xff1a;协议、域名、端口号 必须完全相同。&#xff08;请求是来自同一个服务&#xff09; 跨域&#xff1a;违背了同源策略&#xff0c;即跨域。 ajax请求是遵循…

texshop mac中文版-TeXShop for Mac(Latex编辑预览工具)

texshop for mac是一款可以在苹果电脑MAC OS平台上使用的非常不错的Mac应用软件&#xff0c;texshop for mac是一个非常有用的工具&#xff0c;广泛使用在数学&#xff0c;计算机科学&#xff0c;物理学&#xff0c;经济学等领域的合作&#xff0c;这些程序的标准tetex分布特产…

flask中的session介绍

flask中的session介绍 在Flask中&#xff0c;session是一个用于存储特定用户会话数据的字典对象。它在不同请求之间保存数据。它通过在客户端设置一个签名的cookie&#xff0c;将所有的会话数据存储在客户端。以下是如何在Flask应用中使用session的基本步骤&#xff1a; 首先…

github Recv failure: Connection reset by peer

Recv failure: Connection reset by peer 背景处理ping一下github网页访问一下github项目git配置git ssh配置再次尝试拉取 疑惑点待研究参考 背景 晚上敲着代码准备提交&#xff0c;执行git pull&#xff0c;报错Recv failure: Connection reset by peer。看着这报错我陷入了沉…