( 字符串) 647. 回文子串 ——【Leetcode每日一题】

news2024/11/25 10:37:48

❓647. 回文子串

难度:中等

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

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

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

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

示例 1:

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

示例 2:

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

提示:

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

💡思路:

法一:暴力

两层for循环,遍历区间起始位置和终止位置,然后判断这个区间是不是回文。

时间复杂度: O ( n 3 ) O(n^3) O(n3)

法二:中心扩展法

从字符串的某一位为中心,尝试着在两边扩展子字符串。

  • 可以是奇数长度,也可以是偶数长度。

时间复杂度: O ( n 2 ) O(n^2) O(n2)

法三:动态规划

这一题还可以使用动态规划来进行解决:

  • 状态:dp[i][j] 表示字符串s[i, j]区间的子串是否是一个回文串。
  • 状态转移方程:当 s[i] == s[j] && (j - i < 2 || dp[i + 1][j - 1]) 时,dp[i][j] = true,否则为false

在这里插入图片描述

这个状态转移方程是什么意思呢?

  1. 如果s[i] != s[j]必然不是回文串,所以下面的前提都为s[i] == s[j];
  2. 当只有一个字符时,比如 a 自然是一个回文串; 以及当有两个字符时,如果是相等的,比如 aa,也是一个回文串,所以设置j - i < 2,是回文字符串;
  3. 当有三个及以上字符时,比如 lol 这个字符记作串,把两边的 l 去掉,也就是 o , 如果o为回文串,那么 lol 也一定是回文串。所以当 s[i]==s[j] 时,自然要看 dp[i+1][j-1] 是不是一个回文串。

🍁代码:(Java、C++)

法一:暴力
Java

class Solution {
    public int countSubstrings(String s) {
        int n = s.length();
        int cnt = n;
        for(int len = 2; len <= n; len++){
            for(int i = 0; i + len <= n; i++){
                cnt += isPlim(s.substring(i, i + len)) ? 1 : 0;
            }
        }
        return cnt;
    }
    public boolean isPlim(String s){
        for(int i = 0, j = s.length() - 1; i < j ; i++, j--){
            if(s.charAt(i) != s.charAt(j)) return false;
        }
        return true;
    }
}

C++

class Solution {
public:
    int countSubstrings(string s) {
        int n = s.size();
        int cnt = n;
        for(int len = 2; len <= n; len++){
            for(int i = 0; i + len <= n; i++){
                cnt += isPlim(s.substr(i, len)) ? 1 : 0;
            }
        }
        return cnt;
    }
    bool isPlim(string s){
        for(int i = 0, j = s.size() - 1; i < j; i++, j--){
            if(s[i] != s[j]) return false;
        }
        return true;
    }
};

法二:中心扩展法
Java

class Solution {
    private int cnt = 0;
    public int countSubstrings(String s) {
        for (int i = 0; i < s.length(); i++) {
            extendSubstrings(s, i, i);     // 奇数长度
            extendSubstrings(s, i, i + 1); // 偶数长度
        }
        return cnt;
    }
    private void extendSubstrings(String s, int start, int end) {
        while (start >= 0 && end < s.length() && s.charAt(start) == s.charAt(end)) {
        	cnt++;
            start--;
            end++;
        }
    }
}

C++

class Solution {
public:
    int cnt = 0;
    int countSubstrings(string s) {
        for(int i = 0; i < s.size(); i++){
             extendSubstr(s, i, i);     //奇数长度
             extendSubstr(s, i, i + 1); //偶数长度
        }
        return cnt;
    }
    void  extendSubstr(string s, int start, int end){
        while(start >= 0 && end < s.size() && s[start] == s[end]){
            cnt++;
            start--;
            end++;
        }
    }
};

法三:动态规划
Java

class Solution {
    public int countSubstrings(String s) {
        boolean[][] dp = new boolean[s.length()][s.length()];
        int cnt = 0;
        for (int j = 0; j < s.length(); j++) {
            for (int i = 0; i <= j; i++) {
                if (s.charAt(i) == s.charAt(j) && (j - i < 2 || dp[i + 1][j - 1])) {
                    dp[i][j] = true;
                    cnt++;
                }
            }
        }
        return cnt;
    }
}

C++

class Solution {
public:
    int countSubstrings(string s) {
        vector<vector<bool>> dp(s.size(), vector<bool>(s.size(), false));
        int cnt = 0;
        for (int j = 0; j < s.size(); j++) {
            for (int i = 0; i <= j; i++) {
                if (s[i] == s[j] && (j - i < 2 || dp[i + 1][j - 1])) {
                    dp[i][j] = true;
                    cnt++;
                }
            }
        }
        return cnt;
    }
};

🚀 运行结果:

在这里插入图片描述

🕔 复杂度分析:

  • 时间复杂度 O ( n 2 ) O(n^2) O(n2),其中 n 为字符串的长度,中心扩展法动态规划 O ( n 2 ) O(n^2) O(n2)。。
  • 空间复杂度 O ( 1 ) O(1) O(1)暴力中心扩展法的空间复杂度是 O ( 1 ) O(1) O(1)动态规划 O ( n 2 ) O(n^2) O(n2)

题目来源:力扣。

放弃一件事很容易,每天能坚持一件事一定很酷,一起每日一题吧!
关注我 leetCode专栏,每日更新!

注: 如有不足,欢迎指正!

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

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

相关文章

JSP 的本质原理解析:“编写的时候是JSP,心里想解读的是 java 源码“

JSP 的本质原理解析&#xff1a;“编写的时候是JSP&#xff0c;心里想解读的是 java 源码” 文章目录 JSP 的本质原理解析&#xff1a;"编写的时候是JSP&#xff0c;心里想解读的是 java 源码"每博一文案1. JSP 概述2. 第一个 JSP 程序3. JSP 的本质就是 Servlet4. J…

appium的手动安装步骤教程及appium-doctor报错解决集合

前言 相信你不少软件测试行业小伙伴应该在用npm安装appium或者是cpm安装appium途中也碰到下面一些报错吧&#xff0c;接下来Darren洋教你改为手动安装appium吧&#xff01;整理不易&#xff0c;请点赞加关注后查看。 一、安装Node.js 下载地址&#xff1a; Previous Releases …

【五一创作】某头条参数破解并实现界面化搭建

某条参数破解并实现界面化搭建 前言效果展示难点参数逆向破解_signatureac_signatures_v_web_id 界面化实现总结 前言 趁着日常闲余时间&#xff0c;想着搞一搞某条的反爬&#xff0c;练练手&#xff0c;想到自己很久没开发过前端界面了&#xff0c;有点生疏&#xff0c;也趁此…

PCL学习二:PCL基础应用教程

参考引用 PCL Basic UsagePCL 点云库官网教程 1. pcl_viewer 基本使用 1.1 pcl_viewer 安装测试 pcl_data 源码克隆$ git clone https://github.com/PointCloudLibrary/data.git进入 /pcl_data/tutorials&#xff08;如下图&#xff09;$ cd ~/pcl_data/tutorials # 此处为重…

IDEA常用提升效率的操作小记

IDEA目前是使用最广泛的Java开发工具之一了&#xff0c;虽然是收费的&#xff0c;但是也提供了免费的社区版&#xff0c;并且收费版也支持使用github的开源项目&#xff0c;使用免费license&#xff0c;虽然每年都要续&#xff0c;我用的就是开源项目申请的免费license。 开发…

【Pytorch基础教程39】torch常用tensor处理函数

note 文章目录 note一、tensor的创建二、tensor的加减乘除三、torch.argmax()函数四、gathter函数小栗子1小栗子2&#xff1a;如果每行需要索引多个元素&#xff1a; 四、针对某一维度的操作五、改变维度、拼接、堆叠等操作Reference 一、tensor的创建 torch.tensor会复制data…

STM32配置ADC2(DMA)进行采集 DAC 输出-2

0.一定要先看上一节&#xff1a;STM32配置ADC2&#xff08;DMA&#xff09;进行采集 DAC 输出-2 1.实验目标 在上一节的基础上&#xff0c;我们把 DAC&#xff08;三角波&#xff09;给集成进来&#xff0c;实现按下按键输出三角波&#xff0c;通过串口发送数据给电脑&#x…

Apache Zeppelin系列教程第二篇——整体架构

Zeppelin 架构&#xff1a; 首先我们来了解下 Zeppelin的架构, Zeppelin 主要分3层。 Web前端 Zeppelin Server Interpreter Zeppelin前端负责前端页面的交互&#xff0c;通过Rest API 和WebSocket的方式与Zeppelin Server进行交互。 Zeppelin Server是一个Web server&…

【python 基础语法一】注释,变量与运算符

一、注释 注释: 就是对代码的解释&#xff0c;方便阅读&#xff0c;被注释的代码不执行 分类 单行注释 # 1.单行注释 以#号开头 &#xff0c;右边的所有东西都被当做说明文字 &#xff0c;程序不进行编译运行。 print(hello world)多行注释 # 2.多行注释 三个单引号 或…

Sentinel源码分析学习

文章目录 前言Sentinel源码分析1.Sentinel的基本概念1.1.ProcessorSlotChain1.2.Node1.3.Entry1.3.1.自定义资源1.3.2.基于注解标记资源 1.4.Context1.4.1.什么是Context1.4.2.Context的初始化1.4.2.1.自动装配1.4.2.2.AbstractSentinelInterceptor1.4.2.3.ContextUtil 2.Proce…

django显示echart图表:柱状图、折线图、饼图、地图、词云

django显示echart图表 效果: 示例demo 点我查看 1、urls.py 其中关键代码: urlpatterns = [path("book_chart/", views.book_chart, name="book_cha

LINUX压缩和解压和磁盘管理与维护命令

文章目录 一、压缩和解压命令二、磁盘管理与维护命令总结 一、压缩和解压命令 Linux zip命令:压缩文件或目录 Linux unzip命令:解压文件或目录 Linux tar命令:归档工具 二、磁盘管理与维护命令 Linux df命令:显示磁盘空间使用情况 Linux mount命令:挂载文件系统 Linux quota命…

APK文件结构

文件结构 assets文件用来存放需要打包到Android 应用程序的静态资源文件&#xff0c;例如图片资源文件&#xff0c;JSON配置文件&#xff0c;渠道配置文件&#xff0c;二进制数据文件&#xff0c;HTML5离线资源文件等 与res/raw目录不同的数&#xff0c;assets目录支持任意深度…

数位dp。

一&#xff0c;思想&#xff1a; 在处理1e9甚至1e18,1e100的问题时&#xff0c;因为在统计情况下有很多重复的计算&#xff0c;数位dp实现了相同状态只计算一次&#xff0c;从而大幅减少运算时间&#xff0c;思想就是对每一位进行dp&#xff0c;计算时记忆化每一位可以有的状态…

HashMap机制

反思 HashMap之前只是面试时会看下面试题&#xff0c;但实际从没有撸过源码&#xff0c;对于工作多年的菜鸟来说&#xff0c;对技术不尊重&#xff0c;整理了篇文档&#xff0c;记忆加深一下 原理 假如让我们来设计HashMap实现&#xff0c;我们如何设计一个key->value键值…

4.7排序(C语言)

1.八大排序 加一个计数排序&#xff08;时间复杂度为O(n)&#xff0c; 空间复杂度为O(max(n, range)&#xff0c;非比较排序&#xff09;。 2.希尔排序 3.三个O(n^2)的排序的比较 4.归并排序和快速排序 非递归&#xff1a; 5.排序比较 注意&#xff1a; 下面4种高效排序中&…

【Git】篇一

文章目录 一、Git概述1、版本控制器的方式2、Git的工作流程图 二、Git的安装与常用命令1、Git环境安装2、Git环境基本配置3、获取本地仓库4、基础操作指令 三、分支 一、Git概述 开发中&#xff0c;代码备份、代码还原回滚、追溯、协同开发等场景必不可少&#xff0c;由此&…

特征可视化技术(CAM)

https://zhuanlan.zhihu.com/p/269702192 CAM技术可以帮助我们理解CNN在图像中寻找目标对象的过程&#xff0c;并且可以用于可视化CNN的中间层特征&#xff0c;以及对图像分类结果的解释和可视化。CAM技术的实现比较简单&#xff0c;可以使用常用的深度学习框架如PyTorch和Te…

【C++】模板进阶——非类型模板参数、模板特化、模板分离编译

目录 1.非类型模板参数array 2.模板的特化2.1概念2.2函数模板特化2.3类模板特化1.全特化2.偏特化3.类模板特化应用示例 3.模拟分离编译3.1什么是分离编译3.2模板的分离编译1.问题&#xff1a;2.原因3.解决方法 4.模板总结 1.非类型模板参数 模板参数分为类型形参 与 非类型形参…