LeetCode题解:5.最长回文子串【Python题解超详细,中心拓展、动态规划、暴力解法】

题目描述

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

解答

class Solution(object):def longestPalindrome(self, s):""":type s: str:rtype: str"""# 思路一:中心拓展def extend_from_center(left,right):# 从中心向两侧检测回文while left>=0 and right < len(s) and s[left]==s[right]:left-=1right+=1return s[left+1:right]# 预先声明longest_palindromelongest_palindrome = ""for i in range(0,len(s)):# 奇数回文子串palindrome1=extend_from_center(i,i)# 偶数回文子串palindrome2=extend_from_center(i,i+1)# 迭代最长回文串longest_palindrome=max(longest_palindrome, palindrome1, palindrome2, key=len)return longest_palindrome# # 思路二:动态规划# n = len(s)# if n <= 1:#     return s  # 单字符或空字符串直接返回# # 初始化 dp 表,dp[i][j] 表示 s[i:j+1] 是否是回文# dp = [[False] * n for _ in range(n)]# start, max_length = 0, 1  # 记录最长回文子串的起始位置和长度# # 所有长度为 1 的子串是回文# for i in range(n):#     dp[i][i] = True# # 判断所有长度为 2 的子串是否是回文# for i in range(n - 1):#     if s[i] == s[i + 1]:#         dp[i][i + 1] = True#         start, max_length = i, 2  # 更新最长回文子串的起始位置和长度# # 判断长度大于 2 的子串是否是回文# for length in range(3, n + 1):  # 子串长度从 3 到 n#     for i in range(n - length + 1):  # 起始位置#         j = i + length - 1  # 结束位置#         # 状态转移方程#         if s[i] == s[j] and dp[i + 1][j - 1]:#             dp[i][j] = True#             start, max_length = i, length  # 更新最长回文子串的起始位置和长度# # 返回最长回文子串# return s[start:start + max_length]# # 思路三:暴力解法,遍历所有可能的子串# # 初始化最长回文子串# longest_palindrome = ""# # 遍历所有可能的子串# for i in range(len(s)):#     for j in range(i, len(s)):#         # 获取当前子串#         current_substring = s[i:j + 1]#         # 检查当前子串是否是回文#         if current_substring == current_substring[::-1]:  # 判断回文#             # 如果是回文,并且长度大于当前最长回文,则更新#             if len(current_substring) > len(longest_palindrome):#                 longest_palindrome = current_substring# return longest_palindrome

        思路一,中心拓展法:分奇偶两种情况进行,主要思路是对每个字符及其相邻字符作为中心,向左右两侧扩展,检查形成的最长回文子串。其时间复杂度为O(n^2),因为其对每个字符及其相邻字符作为中心进行扩展,共有 O(n) 个中心,每次扩展的最坏情况是 O(n);其空间复杂度为O(1),因为只使用了常数空间来存储结果,无需额外存储。

        思路二,动态规划法:使用二维数组 dp[i][j] 表示子串 s[i:j+1] 是否是回文。通过递推公式 dp[i][j] = (s[i] == s[j] and dp[i+1][j-1]) 判断每个子串是否是回文,并记录最长的回文子串。其时间复杂度为O(n^2),因为需要遍历每个子串的起始和结束位置以填充 dp 数组,总共有 O(n^2)个状态;其空间复杂度也为O(n^2),因为使用了 O(n^2) 的空间来存储 dp 数组,每个子串的回文状态都被记录下来。

        思路三,暴力解法:遍历所有可能的子串,检查每个子串是否是回文。如果是回文且长度比当前最长的回文子串长,则更新结果。其时间复杂度:为O(n^3),原因在于其遍历所有 O(n^2) 个子串,每个子串检查是否为回文需要 O(n);其空间复杂度为O(1),其只需要常数空间用于结果的存储。

        对比以上三种方法,中心扩展法在代码实现上最简洁,且具有较低的空间复杂度;动态规划法更适合理解和解决子串类的回文问题,但空间开销较大;暴力解法虽易于理解,但实际效率最低。

知识拓展:动态规划初了解

        动态规划(Dynamic Programming, DP)是一种算法设计技术,它用于解决具有重叠子问题和最优子结构特性的问题。动态规划通过将复杂问题分解为更简单的子问题,并存储这些子问题的解(通常是在表格中),从而避免重复计算,提高效率。以下是动态规划的几个关键点:

  1. 重叠子问题:一个问题如果能分解为多个子问题,而这些子问题会重复出现多次,那么这个问题就具有重叠子问题的特性。动态规划通过存储这些子问题的解,使得每个子问题只解决一次。
  2. 最优子结构:如果一个问题的最优解包含其子问题的最优解,那么这个问题就具有最优子结构特性。这意味着我们可以构建一个全局最优解,方法是将子问题的最优解组合起来。
  3. 自底向上: 动态规划通常采用自底向上的方法,即从最小的子问题开始解决,逐步构建到原问题的解。
  4. 状态转移方程:动态规划需要定义状态转移方程,它描述了如何从子问题的解构建出更大问题的解,而这也是动态规划的核心。

        动态规划通常被认为是以空间换取时间的典范,它通过存储中间结果,避免了在递归或迭代过程中对相同子问题的重复计算,能显著减少时间复杂度,尤其适用于那些具有明显递归结构的问题。

动态规划的基本思路

        以本题为例,探究动态规划的基本思路,建议配合上述代码详细查看:

  1. 定义状态

    • 我们定义一个二维布尔数组 dp[i][j],表示子串 s[i:j+1] 是否是回文。
    • 如果 dp[i][j] == True,则 s[i:j+1] 是回文,否则不是。
  2. 状态转移方程

    • 一个字符串 s[i:j+1] 是回文,当且仅当:
      • s[i] == s[j](子串的首尾字符相等),并且
      • s[i+1:j] 也是回文。
    • 因此,状态转移方程为: dp[i][j] = (s[i] == s[j]) and dp[i+1][j-1]

    • 特别地,对于回文的基本起点:
      • 如果子串长度为 1,即 i == j,那么 dp[i][j] = True,因为单个字符是回文。
      • 如果子串长度为 2,即 j = i + 1,只需判断 s[i] == s[j] 是否成立即可。
  3. 初始化

    • 对于所有单个字符 s[i:i+1]dp[i][i] = True,因为单个字符是回文。
    • 对于所有长度为 2 的子串 s[i:i+2],如果 s[i] == s[i+1],则 dp[i][i+1] = True
  4. 计算顺序

    • 我们需要从短到长计算子串的回文性,因为较长的子串依赖于较短的子串的状态。
    • 外层循环控制子串的长度 l,从 2n(字符串长度)。
    • 内层循环控制子串的起始位置 i,计算 j = i + l - 1,并根据状态转移方程填充 dp[i][j]
  5. 结果

    • 在填充 dp 数组的过程中,记录最长回文子串的起始位置和长度。
    • 最后,从字符串 s 中提取出最长的回文子串并返回。

感谢阅读,希望对你有所帮助~

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

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

相关文章

企业一站式管理系统odoo的研究——PLM插件的搭建

大纲 1. 环境准备1.1 安装操作系统1.2 更新操作系统1.3 配置用户组和用户1.3.1 创建用户组 odoo1.3.2. 创建用户 odoo1.3.3. 设置用户 odoo 的密码1.3.4. 验证用户和组1.3.5. 将用户 odoo 添加到添加sudo组&#xff1a;1.3.6. 切到odoo用户 2. 安装 Odoo1. 安装依赖项目2.2. 安…

Keil基于ARM Compiler 5的工程迁移为ARM Compiler 6的工程

环境&#xff1a; keil版本为5.38&#xff0c;版本务必高于5.30 STM32F4的pack包版本要高于2.9 软件包下载地址&#xff1a;https://zhuanlan.zhihu.com/p/262507061 一、更改Keil中编译器 更改后编译&#xff0c;会报很多错&#xff0c;先不管。 二、更改头文件依赖 观察…

ABAP开发学习——ST05 ABAP SQL跟踪工具

操作步骤 第一步使用ST05之前&#xff0c;将要查的程序停留想要看的操作的前一步&#xff0c;这里想看到取数操作&#xff0c;所以停留在选择界面 第二步进入ST05 选择SQL Trace 然后激活 第三步去执行程序 第四步ST05取消激活 第五步查看操作 选完时间直接执行

C/C++语言基础--C++模板与元编程系列六,C++元编程相关库的讲解与使用

本专栏目的 更新C/C的基础语法&#xff0c;包括C的一些新特性 前言 模板与元编程是C的重要特点&#xff0c;也是难点&#xff0c;本人预计将会更新10期左右进行讲解&#xff0c;这是第六期&#xff0c;讲解元编程相关库等&#xff0c;本人感觉这一部分内容还是比较复杂的&am…

uni-app之数据驱动的picker选择器( uni-data-picker)之可以选择到任意级别

背景说明 uni-app 官方的插件市场有数据驱动选择器&#xff0c;可以用作多级分类的场景。本人引入插件后&#xff0c;发现&#xff0c;在h5和微信小程序都只能选择到叶子级。而在给出的官方组件示例中确并非如此。 以选择年级&#xff0c;而不选择班级。然后&#xff0c;想试试…

探索 HTML 和 CSS 实现的蜡烛火焰

效果演示 这段代码是一个模拟蜡烛火焰的HTML和CSS代码。它创建了一个具有动态效果的蜡烛火焰动画&#xff0c;包括火焰的摆动、伸缩和光晕的闪烁。 HTML <div class"holder"><div class"candle"><div class"blinking-glow"&g…

react + ts定义接口类型写法

接口&#xff08;未进行ts定义&#xff09; export async function UserList(params: {// keyword?: string;current?: number;pageSize?: number;},// options?: { [key: string]: any }, ) {return request<API1.UserList>(http://geek.itheima.net/v1_0/mp/artic…

【教程】Ubuntu设置alacritty为默认终端

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;欢迎[点赞、收藏、关注]哦~ 目录 背景介绍 设置教程 注意事项 背景介绍 alacritty是一个开源的终端&#xff0c;比默认的xterm更好看&#xff0c;甚至编辑文本时候还会代码高亮…

使用Element UI实现前端分页,及el-table表格跨页选择数据,切换分页保留分页数据,限制多选数量

文章目录 一、前端分页1、模板部分 (\<template>)2、数据部分 (data)3、计算属性 (computed)4、方法 (methods) 二、跨页选择1、模板部分 (\<template>)2、数据部分 (data)3、方法 (methods) 三、限制数量1、模板部分 (\<template>)2、数据部分 (data)3、方法…

写给初学者的React Native 全栈开发实战班

React Native 全栈开发实战班 亲爱的同学们&#xff1a; 很高兴在这里与大家相聚&#xff01;我是你们的讲师&#xff0c;将带领大家一起踏上 React Native 移动开发的学习之旅。 为什么选择 React Native&#xff1f; 在这个移动互联网时代&#xff0c;App 开发工程师已经…

StarRocks Summit Asia 2024 全部议程公布!

随着企业数字化转型深入&#xff0c;云原生架构正成为湖仓部署的新标准。弹性扩展、资源隔离、成本优化&#xff0c;帮助企业在云上获得了更高的灵活性和效率。与此同时&#xff0c;云原生架构也为湖仓与 AI 的深度融合奠定了基础。 在过去一年&#xff0c;湖仓技术与 AI 的结…

[CKS] K8S Dockerfile和yaml文件安全检测

最近准备花一周的时间准备CKS考试&#xff0c;在准备考试中发现有一个题目关于Dockerfile和yaml文件安全检测的题目。 ​ 专栏其他文章: [CKS] Create/Read/Mount a Secret in K8S-CSDN博客[CKS] Audit Log Policy-CSDN博客 -[CKS] 利用falco进行容器日志捕捉和安全监控-CSDN博…

鸿蒙之多选框(Checkbox)

前言&#xff1a; 控制单个或者多个选项的选中状态&#xff0c;就可以使用 多选框组件 Checkbox:多选框组件CheckboxGroup:多选框组&#xff0c;控制多个多选框 Checkbox: 参数CheckboxOptions说明 名称 类型 必填 描述 name string 否 用于指定多选框名称。一般结合Ch…

CSP/信奥赛C++语法基础刷题训练(8):洛谷P5718:找最小值

CSP/信奥赛C语法基础刷题训练&#xff08;8&#xff09;&#xff1a;洛谷P5718&#xff1a;找最小值 题目描述 给出 n n n 和 n n n 个整数 a i a_i ai​&#xff0c;求这 n n n 个整数中最小值是什么。 输入格式 第一行输入一个正整数 n n n&#xff0c;表示数字个数。…

【云原生系列--Longhorn的部署】

Longhorn部署手册 1.部署longhorn longhorn架构图&#xff1a; 1.1部署环境要求 kubernetes版本要大于v1.21 每个节点都必须装open-iscsi &#xff0c;Longhorn依赖于 iscsiadm主机为 Kubernetes 提供持久卷。 apt-get install -y open-iscsiRWX 支持要求每个节点都安装 N…

【C++】string类(附题)

一、为什么学习string类&#xff1f; 1.1 C语言中的字符串 C语言中&#xff0c;字符串是以\0结尾的一些字符的集合&#xff0c;为了操作方便&#xff0c;C标准库中提供了一些str系列 的库函数&#xff0c;但是这些库函数与字符串是分离开的&#xff0c;不太符合OOP的思想&…

前端vue 列表中回显并下拉选择修改标签

1&#xff0c;vue数据列表中进行回显状态并可以在下拉框中选择修改&#xff0c;效果如下 2&#xff0c;vue 页面关键代码 <el-table-column label"审核" align"center" class-name"small-padding fixed-width" prop"status" >&…

Brave127编译指南 Windows篇:部署Node.js(五)

1. 概述 在Brave浏览器的编译过程中&#xff0c;Node.js扮演着关键角色。作为一个建立在Chrome V8引擎之上的JavaScript运行时环境&#xff0c;Node.js为开发者提供了在服务器端执行JavaScript代码的能力。它的非阻塞、事件驱动架构使其特别适合构建高性能、可扩展的网络应用。…

嵌入式硬件实战提升篇(一)-泰山派RK3566制作多功能小手机

引言&#xff1a;主要针对于嵌入式全栈内容的知识点汇总并对于linux等相关驱动知识点进行串联&#xff0c;用大家参考学习&#xff0c;并用到了嘉立创提供的泰山派RK3566作为学习的主控。 实物演示如下所示&#xff1a; 目录 一、硬件设计 1.转接电路 2.背光电路 3.音频接…

MySQL:数据库的约束

约束类型 NOT NULL - 指示某列不能存储 NULL 值。 UNIQUE - 保证某列的每行必须有唯一的值。 DEFAULT - 规定没有给列赋值时的默认值。 PRIMARY KEY - NOT NULL 和 UNIQUE 的结合。确保某列&#xff08;或两个列多个列的结合&#xff09;有唯一标识&#xff0c;有助于更容易更…