方向一 构造回文字符串问题 刷题解析 | 豆包MarsCode AI刷题

143 阅读3分钟

构造回文字符串问题

小C手中有一个由小写字母组成的字符串 s。她希望构造另一个字符串 t,并且这个字符串需要满足以下几个条件:

  1. t 由小写字母组成,且长度与 s 相同。
  2. t 是回文字符串,即从左到右与从右到左读取相同。
  3. t 的字典序要小于 s,并且在所有符合条件的字符串中字典序尽可能大。

小C想知道是否能构造出这样的字符串 t,输出这样的t。如果无法构造满足条件的字符串,则输出 -1

def solution(s: str) -> str:
    n = len(s)
    s1 = list(s)
    t = s1[:]
    
    # 反转后半部分并判断字典序是否小于原字符串
    for i in range((n + 1) // 2, n):
        t[i] = t[n - i - 1]
    
    if "".join(t) < s:
        return "".join(t)
    else:
        mid = (n + 1) // 2 - 1
        
        # 从中间开始,寻找可以减少的字符
        while mid >= 0 and t[mid] == 'a':
            t[mid] = 'z'  # 将 'a' 替换为 'z'
            mid -= 1
        
        # 如果没有字符可以减少,返回 '-1'
        if mid < 0:
            return "-1"
        else:
            t[mid] = chr(ord(t[mid]) - 1)  # 减小当前字符
        
        # 修复反转部分,确保整体是字典序更小的字符串
        for i in range((n + 1) // 2, n):
            t[i] = t[n - i - 1]
        
        return "".join(t)

1. 初始化与反转

n = len(s)
s1 = list(s)
t = s1[:]
  • n:字符串 s 的长度。
  • s1:将输入字符串 s 转换为字符列表。
  • t:复制一份 s1,用于后续的操作。

2. 反转后半部分并判断字典序

for i in range((n + 1) // 2, n):
    t[i] = t[n - i - 1]
  • t 进行处理,从字符串的中间位置开始,将后半部分的字符替换为与前半部分对称的字符。即,反转后半部分字符,使得 t 成为一个对称的字符串。
if "".join(t) < s:
    return "".join(t)
  • 将修改后的 t 转换为字符串并与原字符串 s 比较,如果 t 小于 s,则直接返回这个修改后的字符串。

3. 中间字符处理

如果反转后得到的字符串 t 仍然大于或等于 s,则开始进行更细的字符调整。

mid = (n + 1) // 2 - 1
  • mid 表示字符串的中间位置,起始于 n // 2 - 1。这一步是为了从中间字符开始修改,尽量让字符串变得字典序更小。

4. 向前调整字符

while mid >= 0 and t[mid] == 'a':
    t[mid] = 'z'
    mid -= 1
  • mid 开始,检查字符是否为 'a',如果是,则将其替换为 'z'。这样可以减少字典序,接着继续检查前面的字符。

5. 判断是否能找到合法的字符

if mid < 0:
    return "-1"
  • 如果 mid 小于 0,说明没有合适的字符可以减少,意味着无法找到字典序比 s 小的字符串,返回 -1

6. 修复字符串并返回结果

else:
    t[mid] = chr(ord(t[mid]) - 1)
  • 如果找到一个字符可以减少,将其减小(通过 ordchr 实现字符的减小)。
for i in range((n + 1) // 2, n):
    t[i] = t[n - i - 1]
  • 调整后的 t 需要再次修复后半部分,确保其是一个有效的对称字符串。

总结

这个算法通过将字符串对称化并调整字符来查找字典序小于给定字符串的最小字符串。如果找不到合适的字符串,则返回 -1。通过从中间字符向前调整,可以有效地优化字典序。