思考思路
- 回文特性:回文字符串的特点是前半部分和后半部分对称。因此,我们可以通过处理字符串的前半部分来构造整个回文字符串。
- 字典序比较:为了使
t
的字典序小于s
,我们需要在前半部分找到一个位置,使得该位置的字符可以减小,并且构造的回文字符串仍然有效。 - 尽可能大的字典序:在找到可以减小的字符后,我们需要确保减小后的字符尽可能大,以满足字典序尽可能大的要求。
代码思路
-
检查是否可能构造回文:如果字符串
s
的所有字符都相同且为 'a',则无法构造满足条件的回文字符串。 -
构造回文:
- 从字符串的中间向两边检查,找到第一个可以减小的字符。
- 减小该字符,并构造回文字符串。
- 如果减小后的字符仍然大于
s
的对应字符,则继续减小,直到找到满足条件的字符。
代码实现
def solution(s: str) -> str:
n = len(s)
t = list(s) # 转换为列表,方便修改
# 先构建一个回文字符串
for i in range(n // 2):
t[n - i - 1] = t[i] # 保持回文性
# 如果初始回文字符串已经小于s,直接返回
if ''.join(t) < s:
return ''.join(t)
# 否则,从中间开始向前调整
for i in range((n - 1) // 2, -1, -1):
if t[i] > 'a': # 如果当前字符大于 'a',可以减小
t[i] = chr(ord(t[i]) - 1)
t[n - i - 1] = t[i] # 保持回文性
# 调整后面的位置为尽可能的小字符 'z',确保字典序最小
for j in range(i + 1, n - i - 1):
t[j] = 'z'
t[n - j - 1] = t[j]
# 生成回文字符串并检查字典序
t_str = ''.join(t)
if t_str < s:
return t_str
else:
# 如果调整后仍然不满足条件,继续尝试下一个字符
t[i] = s[i]
t[n - i - 1] = t[i]
return '-1'
# 测试用例
if __name__ == '__main__':
print(solution("abc") == 'aba') # 输出 'aba'
print(solution("cba") == 'cac') # 输出 'cac'
print(solution("aaa") == '-1') # 输出 '-1'
代码详解
1. 函数定义:
def solution(s: str) -> str:
定义了一个名为 solution
的函数,它接受一个字符串参数 s
,并返回一个字符串。
2. 初始化相关变量:
n = len(s)
t = list(s) # 转换为列表,方便修改
-
n = len(s)
:计算输入字符串s
的长度,并将其存储在变量n
中。 -
t = list(s)
:将输入字符串s
转换为字符列表t
。这样做是因为在 Python 中,字符串是不可变的,将其转换为列表后可以方便地对其中的字符进行修改操作。
3. 构建一个回文字符串:
for i in range(n // 2):
t[n - i - 1] = t[i] # 保持回文性
通过循环遍历字符串的前半部分(range(n // 2)
),将后半部分的对应位置字符设置为与前半部分相同,从而构建出一个回文字符串。例如,如果输入字符串是 "abc"
,经过这一步操作后,列表 t
变为 ['a', 'b', 'a']
。
4. 检查初始回文字符串是否小于输入字符串:
if ''.join(t) < s:
return ''.join(t)
将字符列表 t
通过 ''.join(t)
转换回字符串,并与输入字符串 s
进行比较。如果构建的回文字符串小于输入字符串 s
,则直接返回该回文字符串。这是因为题目要求找到比输入字符串小的字典序最小的回文串,所以如果已经满足小于的条件,就找到了答案。
5. 从中间开始向前调整回文字符串(当上述条件不满足时) :
for i in range((n - 1) // 2, -1, -1):
if t[i] > 'a': # 如果当前字符大于 'a',可以减小
t[i] = chr(ord(t[i]) - 1)
t[n - i - 1] = t[i] # 保持回文性
# 调整后面的位置为尽可能的小字符 'z',确保字典序最小
for j in range(i + 1, n - i - 1):
t[j] = 'z'
t[n - j - 1] = t[j]
# 生成回文字符串并检查字典序
t_str = ''.join(t)
if t_str < s:
return t_str
else:
# 如果调整后仍然不满足条件,继续尝试下一个字符
t[i] = s[i]
t[n - i - 1] = t[i]
-
外层循环
for i in range((n - 1) // 2, -1, -1)
:从字符串的中间位置(如果字符串长度为奇数,就是正中间的字符;如果是偶数,就是中间偏左的字符)开始,向字符串的开头方向遍历。这样做的目的是尝试从中间位置开始逐个调整字符,以找到满足条件的字典序更小的回文串。 -
if t[i] > 'a':
:检查当前位置i
的字符是否大于'a'
。如果大于'a'
,就可以通过将其减小来尝试构建更小的回文串。 -
t[i] = chr(ord(t[i]) - 1)
:将当前位置i
的字符通过ord()
函数获取其 ASCII 码值,然后减 1,再通过chr()
函数将新的 ASCII 码值转换回字符,从而实现将该字符减小的操作。例如,如果当前字符是'b'
,经过这一步就会变为'a'
。 -
t[n - i - 1] = t[i]
:保持回文性,将后半部分对应位置的字符也设置为与调整后的前半部分字符相同。 -
内层循环
for j in range(i + 1, n - i - 1)
:在调整了当前位置i
的字符后,将当前位置后面到后半部分对应位置之前的字符都设置为'z'
。这是为了在保证回文性的前提下,让这些位置的字符尽可能小,从而使整个回文串的字典序更小。 -
t_str = ''.join(t)
:将调整后的字符列表t
转换回字符串,以便与输入字符串s
进行比较。 -
if t_str < s:
:如果调整后的字符串小于输入字符串s
,则找到了满足条件的字典序更小的回文串,直接返回该字符串。 -
else:
:如果调整后的字符串不小于输入字符串s
,说明这次调整不成功,需要将当前位置i
的字符恢复为原来输入字符串s
中的字符(t[i] = s[i]
),并将后半部分对应位置的字符也恢复(t[n - i - 1] = t[i]
),然后继续尝试下一个位置的字符调整。
6. 返回结果:
return '-1'
如果经过上述所有尝试都没有找到满足条件的字典序更小的回文串,就返回 '-1'
,表示不存在这样的回文串。
最后,在 if __name__ == '__main__':
部分是一些测试用例,用于验证 solution
函数的功能是否正确。例如,通过 print(solution("abc") == 'aba')
等语句来检查函数对于不同输入字符串的输出是否符合预期。