codetop打卡第四日

90 阅读1分钟

🌸今天来打卡codetop第四天,今天来一道动态规划的题目,最长回文子串的问题,这道题如果不用动态规划来求解也行,但是面试时,面试官更希望你能用动态规划的思想写出来。🌸\color{#fbbc05}{今天来打卡codetop第四天,今天来一道动态规划的题目,最长回文子串的问题,这道题如果不用动态规划来求解也行,但是面试时,面试官更希望你能用动态规划的思想写出来。}

🌰话不多说,让我们开始今天的学习。🌰\color{#4285f4}{话不多说,让我们开始今天的学习。}

1. 题目描述

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

image.png

解题思路:

  1. 如果采用暴力解法,2个指针,第一个指针确定字符串开始的位置,第二个指针确定结束的位置,双层循环进行判断,判断是否是回文数,如果是,就记录录下该字符串和字符串长度。依次比较,循环结束后取出最长的字符串即可。
  2. 我们这里采用动态规划的解法,动态规划首先要确定的是一种可转移的状态,我们用数组dp[i][j] 来表示 s[i..j] 是否是回文串,是的话dp[i][j]=true 否则为false。状态如何转移呢?如果s[i..j]为回文子串,我们就看s[i-1],s[j+1]这两个元素是否相等,相等的话则为回文数,否者不是。

题解:

def longestPalindrome(self, s: str) -> str:

    n = len(s)

    if n < 2:

        return s

    max_len = 1

    begin = 0

    # dp[i][j] 表示 s[i..j] 是否是回文串

    dp = [[False] * n for _ in range(n)]#构建dp矩阵

    for i in range(n):#单独一个字符肯定是回文数

        dp[i][i] = True

    # 递推开始

    # 先枚举子串长度

    for L in range(2, n + 1):

    # 枚举左边界,左边界的上限设置可以宽松一些

    for i in range(n):

    # 由 L 和 i 可以确定右边界,即 j - i + 1 = L 得

        j = L + i - 1

        # 如果右边界越界,就可以退出当前循环

        if j >= n:

            break

        if s[i] != s[j]:

            dp[i][j] = False

        else:

            if j - i < 3:#dp[i][j]=true且长度小于三肯定是回文数

                dp[i][j] = True

            else:# 状态转移方程

                dp[i][j] = dp[i + 1][j - 1]

      # 只要 dp[i][L] == true 成立,就表示子串 s[i..L] 是回文,此时记录回文长度和起始位置

    if dp[i][j] and j - i + 1 > max_len:

        max_len = j - i + 1

        begin = i

    return s[begin:begin + max_len]

2. 总结

其实关于动态规划,大家可以从上楼梯,机器人寻路问题开始学习。