看题解,学了两种解法:扩散法和DP
1. 扩散法
根据回文串的特性,它是从中间向两边扩散,两边的字符相同。因此定义一个函数:
- 函数的变量是从中间位置扩散的左右端点;
- 满足对称条件时扩散( l–, r++ ),不满足则停止;
- 如果此时对应更大的长度,则更新起始位置和长度
- 变换中间点,重复以上步骤(遍历一下)
- 需要注意,遍历过程中,中间点可能是1个字符(奇对称),也可能2个(偶对称),即 l 和 r 可能相同,也可能 l + 1 = r
def huiwen(s: str):
length = start = 0
def ks(i,j):
nonlocal length, start
while i >= 0 and j < len(s) and s[i] == s[j]:
i -= 1
j += 1
if length < j - i - 1:
length = j - i - 1
start = i + 1
# 因为i、j的运算是在判断其符合要求之后进行的,所以最后i和j都多算了一次
for i in range(len(s)):
ks(i,i)
ks(i,i+1)
return s[start: start + length]
做题的时候卡在 length, start 上,之前一直错误的以为父函数的变量天然是子函数的全局变量,结果定义 ks 函数的时候 length 总被认为没有定义,后来找到原因:
python解释器在处理变量的时候,如果没有出现会去上下文中寻找,如果不需要对这个变量赋值的话,这个变量就利用闭包的特性可以直接使用,如果需要赋值,那么变量会被解释器视作 局部变量,就没有与上文的变量绑定了。使用nonlocal 其实就是告诉编译器,我需要使用上文中的那个变量。
原文在这里:python嵌套函数调用上层函数的局部变量, nonlocal 关键字
2 DP
- i, j 分别是字符串起止下标,i <= j
- 当 s[i+1, j-1] 符合,s[i] == s[j] 时,s[i, j] 符合要求
- 用 dp[i][j] 记录当前下标对应的s是否回文
a = 1 if s[i] == s[j] else 0, dp[i][j] = dp[i+1][j-1] + a, 这种直接用dp记录长度的解法没考虑内部不合题意,外部却符合题意的情况,应该在在内部合理的前提下。- 记下长度和起始位置
def hw(s, n):
if n <= 1: return s
length = 1
start = 0
dp = [[False] * n for _ in range(n)]
for i in range(n):
dp[i][i] = True #起止字符相同时
for j in range(1,n):
for i in range(0,j):
if s[i] == s[j]:
dp[i][j] = s[i] == s[j] and (dp[i+1][j-1] or j-1 - (i+1) < 1)
#当前合理时
if dp[i][j]:
if length < j - i + 1:
length = j - i + 1
start = i
return s[start: start + length]
本文介绍了两种解决回文串问题的方法,一是扩散法,通过从中间扩散判断字符对称性;二是动态规划(DP)法,通过二维数组记录子串是否为回文。在Python中,理解函数作用域是解决问题的关键,nonlocal关键字用于在子函数中引用外部函数的变量。同时,DP解法需考虑内部和外部条件。
830

被折叠的 条评论
为什么被折叠?



