
题目描述
我们称一个长度为偶数的字符串 s
为 反回文 的,如果对于每一个下标 0 <= i < n
,s[i] != s[n - i - 1]
。
给定一个字符串 s
,你需要进行 任意 次(包括 0)操作使 s
成为 反回文。
在一次操作中,你可以选择 s
中的两个字符并且交换它们。
返回结果字符串。如果有多个字符串符合条件,返回 字典序最小 的那个。如果它不能成为一个反回文,返回 "-1"
。
示例 1:
输入:s = "abca"
输出:"aabc"
解释:
"aabc"
是一个反回文字符串,因为 s[0] != s[3]
并且 s[1] != s[2]
。同时,它也是 "abca"
的一个重排。
示例 2:
输入:s = "abba"
输出:"aabb"
解释:
"aabb"
是一个反回文字符串,因为 s[0] != s[3]
并且 s[1] != s[2]
。同时,它也是 "abba"
的一个重排。
示例 3:
输入:s = "cccd"
输出:"-1"
解释:
你可以发现无论你如何重排 "cccd"
的字符,都有 s[0] == s[3]
或 s[1] == s[2]
。所以它不能形成一个反回文字符串。
提示:
2 <= s.length <= 105
s.length % 2 == 0
s
只包含小写英文字母。
解法
方法一:贪心 + 排序
题目要求我们将字符串 \(s\) 变成字典序最小的反回文字符串,我们不妨先对字符串 \(s\) 进行排序。
接下来,我们只需要比较中间的两个字符 \(s[m]\) 和 \(s[m-1]\) 是否相等,如果相等,我们就在后半部分找到第一个不等于 \(s[m]\) 的字符 \(s[i]\),用一个指针 \(j\) 指向 \(m\),然后交换 \(s[i]\) 和 \(s[j]\)。如果找不到这样的字符 \(s[i]\),说明字符串 \(s\) 无法变成反回文字符串,返回 "1"
。否则,执行交换操作,并向右移动 \(i\) 和 \(j\),比较 \(s[j]\) 和 \(s[n-j-1]\) 是否相等,如果相等,继续执行交换操作,直到 \(i\) 超出字符串长度。
时间复杂度 \(O(n \times \log n)\),空间复杂度 \(O(n)\)。其中 \(n\) 是字符串 \(s\) 的长度。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | class Solution:
def makeAntiPalindrome(self, s: str) -> str:
cs = sorted(s)
n = len(cs)
m = n // 2
if cs[m] == cs[m - 1]:
i = m
while i < n and cs[i] == cs[i - 1]:
i += 1
j = m
while j < n and cs[j] == cs[n - j - 1]:
if i >= n:
return "-1"
cs[i], cs[j] = cs[j], cs[i]
i, j = i + 1, j + 1
return "".join(cs)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 | class Solution {
public String makeAntiPalindrome(String s) {
char[] cs = s.toCharArray();
Arrays.sort(cs);
int n = cs.length;
int m = n / 2;
if (cs[m] == cs[m - 1]) {
int i = m;
while (i < n && cs[i] == cs[i - 1]) {
++i;
}
for (int j = m; j < n && cs[j] == cs[n - j - 1]; ++i, ++j) {
if (i >= n) {
return "-1";
}
char t = cs[i];
cs[i] = cs[j];
cs[j] = t;
}
}
return new String(cs);
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 | class Solution {
public:
string makeAntiPalindrome(string s) {
sort(s.begin(), s.end());
int n = s.length();
int m = n / 2;
if (s[m] == s[m - 1]) {
int i = m;
while (i < n && s[i] == s[i - 1]) {
++i;
}
for (int j = m; j < n && s[j] == s[n - j - 1]; ++i, ++j) {
if (i >= n) {
return "-1";
}
swap(s[i], s[j]);
}
}
return s;
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 | func makeAntiPalindrome(s string) string {
cs := []byte(s)
sort.Slice(cs, func(i, j int) bool { return cs[i] < cs[j] })
n := len(cs)
m := n / 2
if cs[m] == cs[m-1] {
i := m
for i < n && cs[i] == cs[i-1] {
i++
}
for j := m; j < n && cs[j] == cs[n-j-1]; i, j = i+1, j+1 {
if i >= n {
return "-1"
}
cs[i], cs[j] = cs[j], cs[i]
}
}
return string(cs)
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | function makeAntiPalindrome(s: string): string {
const cs: string[] = s.split('').sort();
const n: number = cs.length;
const m = n >> 1;
if (cs[m] === cs[m - 1]) {
let i = m;
for (; i < n && cs[i] === cs[i - 1]; i++);
for (let j = m; j < n && cs[j] === cs[n - j - 1]; ++i, ++j) {
if (i >= n) {
return '-1';
}
[cs[j], cs[i]] = [cs[i], cs[j]];
}
}
return cs.join('');
}
|