1. 题目描述
leetcode5: 给你一个字符串
s
,找到s
中最长的回文子串。
解题思路:
- 如果采用暴力解法,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. 总结
其实关于动态规划,大家可以从上楼梯,机器人寻路问题开始学习。