【LeetCode: 5. 最长回文子串 | 暴力递归=>记忆化搜索=>动态规划 => 中心扩展法】

news2024/12/24 3:39:54

在这里插入图片描述

🚀 算法题 🚀

🌲 算法刷题专栏 | 面试必备算法 | 面试高频算法 🍀
🌲 越难的东西,越要努力坚持,因为它具有很高的价值,算法就是这样✨
🌲 作者简介:硕风和炜,CSDN-Java领域新星创作者🏆,保研|国家奖学金|高中学习JAVA|大学完善JAVA开发技术栈|面试刷题|面经八股文|经验分享|好用的网站工具分享💎💎💎
🌲 恭喜你发现一枚宝藏博主,赶快收入囊中吧🌻
🌲 人生如棋,我愿为卒,行动虽慢,可谁曾见我后退一步?🎯🎯

🚀 算法题 🚀

在这里插入图片描述

🍔 目录

    • 🚩 题目链接
    • ⛲ 题目描述
    • 🌟 求解思路&实现代码&运行结果
      • ⚡ 暴力递归
        • 🥦 求解思路
        • 🥦 实现代码
        • 🥦 运行结果
      • ⚡ 记忆化搜索
        • 🥦 求解思路
        • 🥦 实现代码
        • 🥦 运行结果
      • ⚡ 动态规划
        • 🥦 求解思路
        • 🥦 实现代码
        • 🥦 运行结果
      • ⚡ 中心扩展法
        • 🥦 求解思路
        • 🥦 实现代码
        • 🥦 运行结果
    • 💬 共勉

🚩 题目链接

  • 5. 最长回文子串

⛲ 题目描述

给你一个字符串 s,找到 s 中最长的回文子串。

如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。

示例 1:

输入:s = “babad”
输出:“bab”
解释:“aba” 同样是符合题意的答案。
示例 2:

输入:s = “cbbd”
输出:“bb”

提示:

1 <= s.length <= 1000
s 仅由数字和英文字母组成

🌟 求解思路&实现代码&运行结果


⚡ 暴力递归

🥦 求解思路

🥦 实现代码

class Solution {
    public String longestPalindrome(String s) {
        if(s.length()<0||s==null) return null;
        char[] arr=s.toCharArray();
        int n=arr.length;
        String ans = "";
        for(int i=0;i<n;i++){
            for(int j=i;j<n;j++){
                if(process(i,j,arr)&&j-i+1>ans.length()){
                    ans=s.substring(i,j+1);
                }
            }
        }
        return ans;
    }

    public boolean process(int left,int right,char[] arr){
        if(left==right) return true;
        if(left+1==right) return arr[left]==arr[right];
        boolean flag=false;
        if(arr[left]==arr[right]){
            flag|=process(left+1,right-1,arr);
        }
        return flag;
    }
}

🥦 运行结果

时间居然没有超,但是这时间复杂度也太慢了,为了让各位看官大爷有更好的体验,我们还是继续优化。使用我们的锦囊妙计!

在这里插入图片描述


⚡ 记忆化搜索

🥦 求解思路

  1. 根据我们递归的分析,在递归的过程中会产生重复的子过程,所以我们想到了加一个缓存表,也就是我们的记忆化搜索。

🥦 实现代码

class Solution {
    int[][] dp;
    public String longestPalindrome(String s) {
        if(s.length()<0||s==null) return null;
        char[] arr=s.toCharArray();
        int n=arr.length;
        dp=new int[n][n];
        for(int i=0;i<n;i++) Arrays.fill(dp[i],-1);
        String ans = "";
        for(int i=0;i<n;i++){
            for(int j=i;j<n;j++){
                if(process(i,j,arr)&&j-i+1>ans.length()){
                    ans=s.substring(i,j+1);
                }
            }
        }
        return ans;
    }

    public boolean process(int left,int right,char[] arr){
        if(left==right) return true;
        if(left+1==right){
            dp[left][right]=arr[left]==arr[right]?1:0;
            return arr[left]==arr[right];
        }
        if(dp[left][right]!=-1) return dp[left][right]==1;
        boolean flag=false;
        if(arr[left]==arr[right]){
            flag|=process(left+1,right-1,arr);
        }
        dp[left][right]=flag?1:0;
        return flag;
    }
}

🥦 运行结果

傻缓存也还不错!
在这里插入图片描述


⚡ 动态规划

🥦 求解思路

  1. 按照我们之前递归和记忆化搜索的思路,通过动态规划实现出来。

🥦 实现代码

class Solution {
    boolean[][] dp;
    public String longestPalindrome(String s) {
        if(s.length()<0||s==null) return null;
        char[] arr=s.toCharArray();
        int n=arr.length;
        dp=new boolean[n+1][n+1];
        String ans = "";
        for(int left=n-1;left>=0;left--){
            for(int right=left;right<n;right++){
                boolean flag=false;
                if(left==right){
                    dp[left][right]=true; 
                    flag|=true;
                }
                else if(left+1==right){
                    dp[left][right]=arr[left]==arr[right];
                    flag|=dp[left][right];
                }else{
                    if(arr[left]==arr[right]){
                        flag|=dp[left+1][right-1];
                    }
                }
                dp[left][right]=flag;
                if(flag&&right-left+1>ans.length()){
                    ans=s.substring(left,right+1);
                }
            }
        }
        return ans;
    }
}

🥦 运行结果

在这里插入图片描述


⚡ 中心扩展法

🥦 求解思路

  1. 我们可以考虑以每一个位置为中心,向左右位置进行扩展,如果相等,左右指针继续移动,找到该位置最长的回文子串。
  2. 因为我们的回文子串可能为奇数,也可能为偶数,我们可以调用俩次扩展的方法,从i,i 以及i,i+1位置开始,遍历所有结果,找到最长的即可。
  3. 扩展方法我设计的是返回一个数组,res[0]是最长回文子串的开始位置,res[1]是最长回文子串的长度。

🥦 实现代码

class Solution {

    public String longestPalindrome (String A) {
        // write code here
        int len=0;
        int[] res=new int[2];
        for(int i=0;i<A.length();i++){
            int[] res1=process(A,i,i);
            int[] res2=process(A,i,i+1);
            int[] max=res1[1]>res2[1]?res1:res2;
            if(max[1]>len){
                res=max;
                len=res[1];
            }
        }
        return A.substring(res[0],res[0]+res[1]);
    }
     
    public int[] process(String str,int i,int j){
        while(i>=0&&j<str.length()&&str.charAt(i)==str.charAt(j)){
            i--;
            j++;
        }
        return new int[]{i+1,j-i-1};
    }
}

🥦 运行结果

在这里插入图片描述


💬 共勉

最后,我想和大家分享一句一直激励我的座右铭,希望可以与大家共勉!

在这里插入图片描述

在这里插入图片描述

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

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

相关文章

可以一学的代码优化小技巧:减少if-else冗余

前言 if-else 语句对于程序员来说&#xff0c;是非常非常熟悉的一个判断语句&#xff0c;我们在日常开发和学习中都经常看见它&#xff0c;if-else语句主要用于需要做出选择的地方进行判断&#xff0c;这里就不再赘述if-else语法和特点了。 ​ 我们在写代码&#xff08;如图下…

vue---组件逻辑复用方法:Mixin/HOC/Renderless组件

目录 1、Mixin 2、HOC 3、Renderless组件 下文通过表单校验来分别讲解Mixin/HOC/Renderless组件这三种方式。 1、Mixin 通过mixin将一个公用的validate函数同步到每一个组件中去 mixin使用详细介绍见&#xff1a;vue---mixin混入_maidu_xbd的博客-CSDN博客一个混入对象可…

优化Dynamics 365建议

传统上&#xff0c;旧版 Web 客户端需要某些扩展&#xff08;如功能区规则&#xff09;同步返回&#xff0c;这意味着开发人员在从远程源请求数据时被迫使用同步请求。在统一接口中&#xff0c;我们已采取措施确保支持异步通信。例如&#xff1a; 统一接口支持异步功能区规则评…

p67 内网安全-域横向 smbwmi 明文或 hash 传递

数据来源 知识点1&#xff1a; Windows2012以上版本默认关闭wdigest&#xff0c;攻击者无法从内存中获取明文密码 Windows2012以下版本如安装KB2871997补丁&#xff0c;同样也会导致无法获取明文密码 针对以上情况&#xff0c;我们提供了4种方式解决此类问题 利用哈希hash传递&…

Spring Security详细使用

认证流程 1.集中式认证流程 &#xff08;1&#xff09;用户认证 使用UsernamePasswordAuthenticationFilter过滤器中attemptAuthentication方法实现认证功能&#xff0c;该过滤器父类中successfulAuthentication方法实现认证成功后的操作 &#xff08;2&#xff09;身份校验…

基于opencv-python的二值图像处理

目录 阈值 腐蚀与膨胀 开运算与闭运算 连通区域分析 轮廓 一、阈值 按照颜色对图像进行分类&#xff0c;可以分为彩色图像、灰度图像和二值图像。灰度图像是只含亮度信息&#xff0c;不含色彩信息的图像。灰度化处理是把彩色图像转换为灰度图像的过程&#xff0c;是图像处…

【Linux】popen pclose接口介绍

本篇文章简单讲述了c语言接口popen/pclose的用法 1.函数作用 函数定义如下 #include <stdio.h>FILE *popen(const char *command, const char *type); int pclose(FILE *stream);1.1 popen popen函数会创建一个管道&#xff0c;fork后调用shell来打开进程。由于管道的…

Junit 5 如何使用 Guice DI

Guice 是一个依赖注入的小清新工具。 相比 Spring 的依赖管理来说&#xff0c;这个工具更加小巧&#xff0c;我们可以在测试中直接使用。 Junit 5 在 Junit 中使用就没有那么方便了&#xff0c;因为 Junit 没有 Guice 的注解。 你需要手动写一个类&#xff0c;在这个类中&a…

SpringCloud入门实战(七)-Hystrix服务熔断

&#x1f4dd; 学技术、更要掌握学习的方法&#xff0c;一起学习&#xff0c;让进步发生 &#x1f469;&#x1f3fb; 作者&#xff1a;一只IT攻城狮 。 &#x1f490;学习建议&#xff1a;1、养成习惯&#xff0c;学习java的任何一个技术&#xff0c;都可以先去官网先看看&…

Spring的作用域与生命周期

文章目录 一、lombok的安装与使用二、Spring作用域二、Bean原理分析执行流程Bean的生命周期 一、lombok的安装与使用 lombok插件可以提供给我们一些注释&#xff0c;这些注释可以很好的帮助我们消除Java代码中大量冗余的代码&#xff0c;可以使得我们的Java类可以看起来非常的…

OpenCV实战——二值特征描述符

OpenCV实战——二值特征描述符 0. 前言1. ORB 和 BRISK 二值描述符1. ORB 特征描述符1.2 ORB 与 BRISK 算法 2. FREAK 二值描述符3. 二值描述符采样模式4. 完整代码相关链接 0. 前言 在《特征描述符》一节中&#xff0c;我们学习了如何使用从图像强度梯度中提取的描述符来描述…

ChatGPT使用学习(一):chatgpt_academic安装到测试详细教程(一文包会)

ChatGPT 1.简介及功能2.前置准备3.开始使用 1.简介及功能 Chargpt academic是一种基于OpenAI GPT模型的语言生成模型&#xff0c;它是专门为学术研究者和学生设计的。它使用预训练模型来生成与学术论文、文章和文献相关的文本&#xff0c;可以用于自然语言处理、机器翻译、文本…

SpringBoot整合Redis,一篇带你入门使用Redis

本文介绍如何将Redis整合到SpringBoot项目中&#xff0c;以及如何配置、封装和使用 文章目录 前言环境搭建项目结构添加依赖 Module封装RedisConfig配置封装常见操作为ServiceRedisServiceRedisLockUtil 测试 前言 参考链接&#xff1a; 英文官网链接中文官网链接Redis githu…

vue项目使用RSA加解密

vue项目使用RSA加解密 1.安装2.在utils下创建rsa.js3.在main.js中引入4.页面调用5.遇到的问题 1.安装 使用一下命令安装jsencrypt插件 npm install jsencrypt --save-dev npm i encryptlong -S注意&#xff1a; &#xff08;1&#xff09;上述插件不支持在小程序中使用&#…

python大数据作业-客户价值分析-实训头歌

一、实验目的与要求 1、掌握使用numpy和pandas库处理数据的基本方法。 2、掌握使用RFM分析模型对客户信息进行特征提取的基本方法。 3、掌握对特征数据进行标准化处理的基本方法。 4、掌握使用Sklearn库对K-Means聚类算法的实现及其评价方法。 5、掌握使用matplotlib结合panda…

【2】YOLOv8原理解析:重新定义实时目标检测的速度和精度

文章目录 0.前言1.YOLOv51.1 YOLOv5网络回顾1.2 YOLOv5网络结构图 2.YOLOv82.1 YOLOv8概述2.2 YOLOv8整体结构图2.3 YOLOv8yaml 文件与 YOLOv5yaml 文件对比2.3.1 参数部分2.3.2 主干部分2.3.3 Neck部分2.3.4 Head部分 2.4 正负样本分配策略2.4.1 静态分配策略和动态分配策略有…

机器学习实战:Python基于SVD奇异值分解进行矩阵分解(八)

文章目录 1 前言1.1 奇异值分解1.2 奇异值分解的应用 2 简单计算SVD2.1 NumPy 计算 SVD2.2 scikit-learn 计算截断 SVD2.3 scikit-learn 计算随机 SVD 3 demo数据演示3.1 导入函数3.2 导入数据3.3 计算SVD 4 讨论 1 前言 1.1 奇异值分解 奇异值分解&#xff08;Singular Valu…

【李老师云计算】实验二:Spark集群的搭建与求解最大值

索引 前言1. Spark部署1.1 下载Spark1.2 解压Spark1.3 修改环境变量1.4 修改主机Spark配置文件1.4.1 slaves.template文件配置1.4.2 spark-env.sh.template文件配置 1.5 分享主机Spark到从机1.6 启动Spark集群(★重启后的操作)1.7 通过jps查看是否启动成功1.8 通过网页查看是否…

Vue+Echarts 项目演练(上)整体页面结构的构建

项目分辨率响应式创建 项目顶部信息条创建 页面主体创建 接项目搭建与初始化之后继续对项目进行部署工作 项目展示&#xff1a; 技术栈&#xff1a; 1. vue3.0vue-router4.0axios 2. flex 布局 3. LESS 4. rem 屏幕适配 5. echarts5.0 项目分辨率响应式创建 对插件…

centos 8 配置LVS+ keepalived 高可用

♥️作者&#xff1a;小刘在C站 ♥️个人主页&#xff1a;小刘主页 ♥️每天分享云计算网络运维课堂笔记&#xff0c;努力不一定有收获&#xff0c;但一定会有收获加油&#xff01;一起努力&#xff0c;共赴美好人生&#xff01; ♥️夕阳下&#xff0c;是最美的绽放&#xff0…