当前位置: 首页 > news >正文

力扣Leetcode:5. 最长回文子串(Python)

题目描述

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

题解:动态规划

这是一道很经典的题目。首先我想到了动态规划算法:

对于子串s[i…j],它为回文子串的条件为:s[i+1 … j-1]为回文子串,且s[i]==s[j]。想到这里,状态转移方程就已经显然易见了。

那么初始状态呢?我们的状态转移方程是从短的子串向长的子串转移的,因此外循环应该是子串长度。当子串长度为1,也就是只有一个字符时,显然为回文子串,这就是初始状态。

由于要返回最长的回文子串(SJ),因此需要记录一下。

该算法的时间复杂度为O(n2),空间复杂度也是O(n2)。

两个关于Python语法的点

  • 定义二维数组
dp = [[True for _ in range(n)] for _ in range(n)]
  • 切片:切片结果不包括end_index!

代码一:动态规划(Python)

class Solution:
    def longestPalindrome(self, s: str) -> str:
        n = len(s)
        best_l, best_i = 0, 0
        if n < 2:
            return s
        dp = [[Fasle for _ in range(n)] for _ in range(n)]
        for i in range(n):
            dp[i][i] = True       
        for l in range(1, n):
            for i in range(n):
                if i + l < n:
                    dp[i][i+l] = s[i] == s[i+l] and dp[i+1][i+l-1] if l > 1 else s[i] == s[i+l]
                    if dp[i][i+l] and l > best_l:
                        best_i, best_l = i, l
        return s[best_i:best_i+best_l+1]

提交上述代码,发现TLE。下一步,在不改变算法时间复杂度的前提下,作语句优化(其实就是牺牲一定的可读性,换取更高的执行效率):

class Solution:
    def longestPalindrome(self, s: str) -> str:
        n = len(s)
        best_l, best_i = 0, 0
        if n < 2:
            return s
        dp = [[False] * n for _ in range(n)]
        for i in range(n):
            dp[i][i] = True
        for l in range(1, n):
            for i in range(n):
                j = i + l
                if j < n:
                    if s[i] == s[j]:
                        if l == 1:
                            dp[i][j] = True
                        else:
                            dp[i][j] = dp[i+1][j-1]
                    if dp[i][j]:
                        best_i, best_l = i, l
        return s[best_i:best_i+best_l+1]

改进 修改后的代码是通过的。可以观察到,显然代码行数变多了。但对于机器执行来说,速度变快了。

进一步改进:分析状态转移路径

虽然到这里其实已经完事了,但对于动态规划算法来说,(或许)可以通过分析状态转移路径的方法作进一步空间优化。

两种分析思路:

  • 正向(拓展):
    dp[i][i]作为起点,只会决定dp[i-1][i+1],下一步只会决定dp[i-2][i+2],传递路径是单链的。
  • 反向(递归):
    dp[i][j]仅取决于dp[i+1][j-1],下一步仅取决于dp[i+2][j-2],传递路径同样是单链的。

因此,我们利用正向传递的单链性质,通过“拓展”的方式设计算法。需要注意的是,对于奇数长度与偶数长度的回文子串,它们的回文中心是不同的,需要分情况讨论。官方题解中有这样一句话:

我们枚举所有的「回文中心」并尝试「扩展」,直到无法扩展为止,此时的回文串长度即为此「回文中心」下的最长回文串长度。

这里的“拓展”,其实本质上还是动态规划。该算法共选择了n次扩展中心,每次至多扩展n次,因此时间复杂度为O(n2)。该算法没有占用额外的存储空间。这与“分析状态转移路径能够在保证时间不变的前提下优化空间”一致。

代码二:拓展法(Python)

    def longestPalindrome(self, s: str) -> str:
        n = len(s)
        best_l, best_r = 0, 0
        for i in range(n):
            for delta in [0, 1]: # 分别讨论奇数长度与偶数长度
                l, r = i, i + delta
                while l >= 0 and r < n and s[l] == s[r]:
                    if r - l > best_r - best_l:
                        best_l, best_r = l, r
                    l, r = l-1, r+1
                l, r = i, i+1
        return s[best_l: best_r+1]

相关文章:

  • 古诗词推荐(一):春风十里扬州路,卷上珠帘总不如
  • 终于签完了
  • 古诗词推荐(二):若似月轮终皎洁,不辞冰雪为卿热
  • 腾讯面经zz
  • 力扣Leetcode:10. 正则表达式匹配(Python)
  • 从《关于跳槽的切身体会(转)》谈转载文章的职业道德!!!
  • 力扣Leetcode:11. 盛最多水的容器(Python、Java)
  • 劝学诗整理:安居不用架高堂,书中自有黄金屋。
  • 服务器群集:Windows Server 2003 备份和恢复的最佳做法
  • 力扣Leetcode:15. 三数之和(Python)
  • 忙了一下午
  • 力扣Leetcode:17. 电话号码的字母组合(Python)
  • 新的生活:)
  • 报错解决:力扣提交后的执行结果与执行代码的结果不一致(解答错误)
  • 力扣LeetCode:19. 删除链表的倒数第 N 个结点(Python)
  • 【5+】跨webview多页面 触发事件(二)
  • Elasticsearch 参考指南(升级前重新索引)
  • ES6系统学习----从Apollo Client看解构赋值
  • Invalidate和postInvalidate的区别
  • Java 内存分配及垃圾回收机制初探
  • JavaScript学习总结——原型
  • leetcode-27. Remove Element
  • SegmentFault 2015 Top Rank
  • Terraform入门 - 1. 安装Terraform
  • TiDB 源码阅读系列文章(十)Chunk 和执行框架简介
  • 极限编程 (Extreme Programming) - 发布计划 (Release Planning)
  • 使用parted解决大于2T的磁盘分区
  • No resource identifier found for attribute,RxJava之zip操作符
  • PostgreSQL 快速给指定表每个字段创建索引 - 1
  • Salesforce和SAP Netweaver里数据库表的元数据设计
  • ​【原创】基于SSM的酒店预约管理系统(酒店管理系统毕业设计)
  • (阿里云万网)-域名注册购买实名流程
  • (第二周)效能测试
  • (附源码)node.js知识分享网站 毕业设计 202038
  • (一)ClickHouse 中的 `MaterializedMySQL` 数据库引擎的使用方法、设置、特性和限制。
  • (原創) 如何動態建立二維陣列(多維陣列)? (.NET) (C#)
  • .net 8 发布了,试下微软最近强推的MAUI
  • .NET HttpWebRequest、WebClient、HttpClient
  • .Net mvc总结
  • .net 无限分类
  • .NET/C# 反射的的性能数据,以及高性能开发建议(反射获取 Attribute 和反射调用方法)
  • .NET中的Exception处理(C#)
  • .secret勒索病毒数据恢复|金蝶、用友、管家婆、OA、速达、ERP等软件数据库恢复
  • /bin/rm: 参数列表过长"的解决办法
  • @EnableAsync和@Async开始异步任务支持
  • @JsonFormat与@DateTimeFormat注解的使用
  • @TableLogic注解说明,以及对增删改查的影响
  • [20170713] 无法访问SQL Server
  • [BZOJ] 2006: [NOI2010]超级钢琴
  • [CF]Codeforces Round #551 (Div. 2)
  • [flask] flask的基本介绍、flask快速搭建项目并运行
  • [Hive] CTE 通用表达式 WITH关键字
  • [HJ56 完全数计算]
  • [LeetCode][LCR178]训练计划 VI——使用位运算寻找数组中不同的数字
  • [linux] shell中的()和{}