AI刷题 37.构造回文字符串问题 | 豆包MarsCode AI刷题

138 阅读3分钟

学习笔记:构造字典序最大且小于原字符串的回文字符串

问题背景

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

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

如果无法构造满足条件的字符串 t,则输出 -1

问题分析

  1. 回文字符串的特性:回文字符串的特点是从中间向两边对称。因此,我们可以将字符串分为两部分:前半部分和后半部分(如果有奇数个字符,中间的字符单独处理)。
  2. 字典序的要求:构造的字符串 t 必须小于原字符串 s,并且在所有满足条件的字符串中字典序尽可能大。
  3. 构造方法
    • 先构造前半部分,使其尽可能接近 s 的前半部分。
    • 然后根据前半部分构造后半部分,使其成为回文字符串。
    • 如果中间有字符,单独处理,使其尽可能大但仍小于 s 的对应字符。

解决方案

  1. 初始化

    • 获取字符串 s 的长度 n
    • 计算中间字符 mid(如果 n 是奇数)。
    • 获取前半部分 half
  2. 处理中间字符

    • 如果 mid 不为空且大于 'a',尝试将其减1,构造回文字符串并检查是否小于 s
    • 如果 mid 为空或等于 'a',将其设为 'z'
  3. 处理前半部分

    • 从右半部分的末尾开始向前遍历,尝试将每个字符减1,构造回文字符串并检查是否小于 s
    • 如果找到一个合适的字符,构造回文字符串并返回。
    • 如果所有字符都已处理完毕且无法构造满足条件的字符串,返回 -1

代码实现

def solution(s: str) -> str:
    n = len(s)
    mid = s[n // 2] if n % 2 != 0 else ''
    half = s[:n // 2]
    
    # 处理中间字符
    if mid > "a":
        new_mid = chr(ord(mid) - 1)
        candidate = half + new_mid + half[::-1]
        if candidate < s:
            return candidate
        return half + new_mid + half[::-1]
    
    # 如果中间字符为空或等于 'a'
    if mid != "":
        mid = "z"
    
    right_half = half[::-1]
    for i in range(len(right_half)):
        cur = right_half[i]
        if cur > "a":
            new_right = right_half[:i] + chr(ord(cur) - 1) + right_half[i + 1:]
            candidate = new_right[::-1] + mid + new_right
            if candidate < s:
                return candidate
    
    # 如果所有字符都已处理完毕且无法构造满足条件的字符串
    return "-1"

详细解释

  1. 初始化

    • n = len(s) 获取字符串 s 的长度。
    • mid = s[n // 2] if n % 2 != 0 else '' 计算中间字符(如果 n 是奇数)。
    • half = s[:n // 2] 获取前半部分。
  2. 处理中间字符

    • 如果 mid 不为空且大于 'a',尝试将其减1,构造回文字符串并检查是否小于 s
    • 如果构造的回文字符串小于 s,直接返回。
    • 否则,将 mid 设为 'z'
  3. 处理前半部分

    • right_half = half[::-1] 获取前半部分的逆序。
    • 从右半部分的末尾开始向前遍历,尝试将每个字符减1,构造回文字符串并检查是否小于 s
    • 如果找到一个合适的字符,构造回文字符串并返回。
    • 如果所有字符都已处理完毕且无法构造满足条件的字符串,返回 -1

通过上述方法,我们可以有效地解决这个问题,并通过测试用例验证其正确性。