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.执行结果


浙公网安备 33010602011771号