Leetcode 3088. 使字符串反回文

1.题目基本信息

1.1.题目描述

我们称一个长度为偶数的字符串 s 为 反回文 的,如果对于每一个下标 0 <= i < n ,s[i] != s[n - i - 1]。

给定一个字符串 s,你需要进行 任意 次(包括 0)操作使 s 成为 反回文。

在一次操作中,你可以选择 s 中的两个字符并且交换它们。

返回结果字符串。如果有多个字符串符合条件,返回 字典序最小 的那个。如果它不能成为一个反回文,返回 "-1"。

1.2.题目地址

https://leetcode.cn/problems/make-string-anti-palindrome/description/

2.解题方法

2.1.解题思路

贪心

2.2.解题步骤

第一步,统计s中各个字符的频数,以及特殊情况处理。当s中某一个字符个数超过长度的一半,那么一定不能操作使其成为反回文串,直接返回"-1"即可。反之,按各个字符的字典序连续的连接起来,形成一个新的字符串,记为s1

第二步,记n=len(s1),如果正中间的两个字符相等,则直接返回s1(此时就是反回文串了);反之,如果中间的两个字符相等,记中间字符的前段长度为r1,则需要中间后面r1的部分替换为非中间字符,等价于将s1[n//2-1]的下一个不同字符后面的连续d个字符子串移动到正中间(d为此时中间字符子串的前部分的长度)

2.1.计算回文串后半段需要移动的距离,即为中间回文串前半段的长度

2.2.求不同于正中间字符的下一个不同字符及其初始位置

2.3.进行最终字符串合并,模拟回文串右段的移动

第三步,返回结果

3.解题代码

Python代码

class Solution:
    def makeAntiPalindrome(self, s: str) -> str:
        # 思路:贪心
        # 第一步,统计s中各个字符的频数,以及特殊情况处理。当s中某一个字符个数超过长度的一半,那么一定不能操作使其成为反回文串,直接返回"-1"即可。反之,按各个字符的字典序连续的连接起来,形成一个新的字符串,记为s1
        n = len(s)
        cnt = Counter(s)
        s1 = ""
        for c in sorted(cnt.keys()):
            if cnt[c] > n // 2:
                return "-1"
            s1 += c * cnt[c]
        # print(s1)
        # 第二步,记n=len(s1),如果正中间的两个字符相等,则直接返回s1(此时就是反回文串了);反之,如果中间的两个字符相等,记中间字符的前段长度为r1,则需要中间后面r1的部分替换为非中间字符,等价于将s1[n//2-1]的下一个不同字符后面的连续d个字符子串移动到正中间(d为此时中间字符子串的前部分的长度)
        if s1[n // 2 - 1] != s1[n // 2]:
            return s1
        # 2.1.计算回文串后半段需要移动的距离,即为中间回文串前半段的长度
        d = 0
        i1, i2 = n // 2 - 1, n // 2
        while s1[i1 - d] == s1[n // 2]:
            d += 1
        # print("d", d)
        # 2.2.求不同于正中间字符的下一个不同字符及其初始位置
        j = n // 2 + 1
        while s1[j] == s1[n // 2]:
            j += 1
        c1 = s1[j]
        # print("c1", c1)
        # print(s1[:n // 2], s1[n // 2:])
        # 2.3.进行最终字符串合并,模拟回文串右段的移动
        result = s1[: n // 2] + s1[j: j + d] + s1[n // 2 : j] + s1[j + d:]
        # print(result)
        # 第三步,返回结果
        return result

4.执行结果

posted @ 2025-06-04 09:37  Geek0070  阅读(11)  评论(0)    收藏  举报