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"即可。反之,按各个字符的字典序连续的连接起来,形成一个新的字符串,记为s1n = 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 = 0i1, i2 = n // 2 - 1, n // 2while s1[i1 - d] == s1[n // 2]:d += 1# print("d", d)# 2.2.求不同于正中间字符的下一个不同字符及其初始位置j = n // 2 + 1while s1[j] == s1[n // 2]:j += 1c1 = 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