字典序最小回文构造问题——解题笔记
问题描述
给定一个由小写英文字母组成的字符串 s,需要将其转换为一个回文字符串,且要求在最多修改 两个字符 的前提下,使得结果字符串的 字典序最小。
例如:
- 对于字符串
"acca",可以通过修改两个字符得到回文字符串"aaaa",这是字典序最小的解。
解题思路
这个问题需要在限制条件下(最多修改两个字符)将字符串转换为字典序最小的回文字符串。
主要挑战:
- 在保证回文的前提下,使字典序尽可能小。
- 修改次数不能超过两次。
为了解决这个问题,需要从以下几个方面考虑:
-
构造回文字符串: 首先,需要确保最终的字符串是回文的。如果原字符串已经是回文,那么我们需要在不超过两次修改的情况下,尽可能降低其字典序。
-
字典序最小化: 在构造回文的过程中,尽可能将字符修改为
'a',因为'a'是字典序最小的字母。 -
修改次数限制: 我们需要在整个过程中跟踪修改次数,确保不超过两次。
解决方案
步骤一:使字符串成为回文
- 遍历字符串的前半部分,将每个字符与其对称位置的字符进行比较。
- 如果两个字符不相同,我们需要修改其中的一个字符,使得它们相同,以构成回文。
- 为了使字典序最小,选择较小的字符 替换较大的字符。
- 每次修改都计数,确保总修改次数不超过两次。
步骤二:字典序最小化
- 再次遍历字符串的前半部分。
- 如果当前字符不是
'a',我们可以尝试将其修改为'a',同时也要修改对称位置的字符以保持回文性。 - 每次这样的修改会消耗两次修改机会(因为需要修改两个字符)。
- 在修改之前,检查剩余的修改次数是否足够(不能超过两次修改)。
步骤三:处理字符串长度为奇数的情况
- 如果字符串长度为奇数,且还有剩余的修改次数,我们可以尝试将中间的字符修改为
'a',进一步减小字典序。
代码实现
def solution(s: str) -> str:
res = list(s)
n = len(res)
changes_used = 0
# 步骤一:使字符串成为回文
for i in range(n // 2):
if res[i] != res[n - 1 - i]:
min_char = min(res[i], res[n - 1 - i])
if res[i] != min_char:
res[i] = min_char
changes_used += 1
if res[n - 1 - i] != min_char:
res[n - 1 - i] = min_char
changes_used += 1
if changes_used > 2:
return "Not possible"
# 步骤二:字典序最小化
for i in range(n // 2):
if res[i] != 'a':
if changes_used + 2 <= 2:
res[i] = res[n - 1 - i] = 'a'
changes_used += 2
else:
break
# 步骤三:处理中间字符(针对奇数长度字符串)
if n % 2 == 1 and changes_used < 2:
if res[n // 2] != 'a':
res[n // 2] = 'a'
changes_used += 1
return ''.join(res)
测试样例验证
if __name__ == "__main__":
print(solution("acca") == "aaaa") # 输出:True
print(solution("racecar") == "aacecaa") # 输出:True
print(solution("fecdef") == "feccef") # 输出:True
-
样例1:
- 输入:
"acca" - 输出:
"aaaa" - 解释:修改了两个字符,将
'c'改为'a'。
- 输入:
-
样例2:
- 输入:
"racecar" - 输出:
"aacecaa" - 解释:修改首尾两个
'r'为'a'。
- 输入:
-
样例3:
- 输入:
"fecdef" - 输出:
"feccef" - 解释:修改中间的
'd'为'c'。
- 输入:
总结
这道题考察了字符串操作和贪心算法的应用。在限制修改次数的情况下,需要:
- 优先保证回文性:必要时修改字符使字符串成为回文。
- 在保证回文的前提下,尽可能降低字典序:尽量将字符修改为
'a'。 - 严格控制修改次数:任何修改都需要检查是否超出限制。
通过以上策略,我们可以在 O(n) 的时间复杂度内得到满足条件的字典序最小的回文字符串。