每天练习python-最长回文数

文章介绍了如何使用动态规划方法解决寻找给定字符串中最长回文子串的问题。通过状态转移方程dp[i][j]=(s[i]==s[j]anddp[i+1][j-1]),可以判断子串是否为回文,并逐步构建最长回文子串。代码示例使用Python实现,具有O(n^2)的时间复杂度。
摘要由CSDN通过智能技术生成

题目:

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

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

思路

我们可以使用动态规划来解决这个问题。具体地,设状态 dp[i][j] 表示字符串 s 的子串 s[i:j+1] 是否为回文串。那么,如果 s[i:j+1] 是回文串,那么 s[i+1:j] 也一定是回文串,即 dp[i+1][j-1] = True;否则,s[i:j+1] 不是回文串。

注意到一个回文串去掉首位字符后仍然是回文串。因此,我们可以根据子串的长度进行推导。具体地,对于每个 i 和 j,我们首先判断 s[i] 和 s[j] 是否相等。如果相等,那么如果 s[i+1:j] 是回文串,那么 s[i:j+1] 也一定是回文串;否则,s[i:j+1] 不是回文串。如果 s[i] 和 s[j] 不相等,那么 s[i:j+1] 不是回文串。

当子串长度为 1 或者 2 时,容易推出其是否为回文串。因此,我们可以从子串长度为 3 开始逐步向上推导,直到整个字符串。最终,最长回文子串即为所有 dp[i][j] = True 中最长的一个。

代码实现

class Solution(object):
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        n = len(s)
        dp = [[False] * n for _ in range(n)]
        ans = ""
        # 枚举子串长度 l+1
        for l in range(n):
            for i in range(n):
                j = i + l
                if j >= n:
                    break
                if l == 0:
                    dp[i][j] = True
                elif l == 1:
                    dp[i][j] = (s[i] == s[j])
                else:
                    dp[i][j] = (s[i] == s[j] and dp[i+1][j-1])
                if dp[i][j] and l + 1 > len(ans):
                    ans = s[i:j+1]
        return ans

在上面的代码中,我们首先创建一个二维数组 dp,并初始化所有的 dp[i][j] = False(默认不是回文串)。随后,我们依次枚举子串的长度 l+1 和起始位置 i,并计算结束位置 j。如果子串的长度为 1 或者 2,则容易计算其是否为回文串。否则,我们需要根据状态转移方程 dp[i][j] = (s[i] == s[j] and dp[i+1][j-1]) 来判断该子串是否为回文串。

由于每个状态只与其左下方的状态有关,因此可以使用滚动数组将空间复杂度优化到 O(n)。总时间复杂度为 O(n^2),其中 n 是字符串 s 的长度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是萧萧吖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值