题目描述
如果字符串中的所有字符都相同,那么这个字符串是单字符重复的字符串。
给你一个字符串 text
,你只能交换其中两个字符一次或者什么都不做,然后得到一些单字符重复的子串。返回其中最长的子串的长度。
示例 1:
输入:text = "ababa"
输出:3
示例 2:
输入:text = "aaabaaa"
输出:6
示例 3:
输入:text = "aaabbaaa"
输出:4
示例 4:
输入:text = "aaaaa"
输出:5
示例 5:
输入:text = "abcdef"
输出:1
提示:
1 <= text.length <= 20000
text
仅由小写英文字母组成。
解法
方法一:双指针
我们先用哈希表或数组 $cnt$ 统计字符串 $text$ 中每个字符出现的次数。
接下来,我们定义一个指针 $i$,初始时 $i = 0$。每一次,我们将指针 $j$ 指向 $i$,并不断地向右移动 $j$,直到 $j$ 指向的字符与 $i$ 指向的字符不同,此时我们得到了一个长度为 $l = j - i$ 的子串 $text[i..j-1]$,其中所有字符都相同。
然后我们跳过指针 $j$ 指向的字符,用指针 $k$ 继续向右移动,直到 $k$ 指向的字符与 $i$ 指向的字符不同,此时我们得到了一个长度为 $r = k - j - 1$ 的子串 $text[j+1..k-1]$,其中所有字符都相同。那么我们最多通过一次交换操作,可以得到的最长单字符重复子串的长度为 $\min(l + r + 1, cnt[text[i]])$。接下来,我们将指针 $i$ 移动到 $j$,继续寻找下一个子串。我们取所有满足条件的子串的最大长度即可。
时间复杂度为 $O(n)$,空间复杂度 $O(C)$。其中 $n$ 为字符串的长度;而 $C$ 为字符集的大小,本题中 $C = 26$。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | class Solution:
def maxRepOpt1(self, text: str) -> int:
cnt = Counter(text)
n = len(text)
ans = i = 0
while i < n:
j = i
while j < n and text[j] == text[i]:
j += 1
l = j - i
k = j + 1
while k < n and text[k] == text[i]:
k += 1
r = k - j - 1
ans = max(ans, min(l + r + 1, cnt[text[i]]))
i = j
return ans
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 | class Solution {
public int maxRepOpt1(String text) {
int[] cnt = new int[26];
int n = text.length();
for (int i = 0; i < n; ++i) {
++cnt[text.charAt(i) - 'a'];
}
int ans = 0, i = 0;
while (i < n) {
int j = i;
while (j < n && text.charAt(j) == text.charAt(i)) {
++j;
}
int l = j - i;
int k = j + 1;
while (k < n && text.charAt(k) == text.charAt(i)) {
++k;
}
int r = k - j - 1;
ans = Math.max(ans, Math.min(l + r + 1, cnt[text.charAt(i) - 'a']));
i = j;
}
return ans;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 | class Solution {
public:
int maxRepOpt1(string text) {
int cnt[26] = {0};
for (char& c : text) {
++cnt[c - 'a'];
}
int n = text.size();
int ans = 0, i = 0;
while (i < n) {
int j = i;
while (j < n && text[j] == text[i]) {
++j;
}
int l = j - i;
int k = j + 1;
while (k < n && text[k] == text[i]) {
++k;
}
int r = k - j - 1;
ans = max(ans, min(l + r + 1, cnt[text[i] - 'a']));
i = j;
}
return ans;
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 | func maxRepOpt1(text string) (ans int) {
cnt := [26]int{}
for _, c := range text {
cnt[c-'a']++
}
n := len(text)
for i, j := 0, 0; i < n; i = j {
j = i
for j < n && text[j] == text[i] {
j++
}
l := j - i
k := j + 1
for k < n && text[k] == text[i] {
k++
}
r := k - j - 1
ans = max(ans, min(l+r+1, cnt[text[i]-'a']))
}
return
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 | function maxRepOpt1(text: string): number {
const idx = (c: string) => c.charCodeAt(0) - 'a'.charCodeAt(0);
const cnt: number[] = new Array(26).fill(0);
for (const c of text) {
cnt[idx(c)]++;
}
let ans = 0;
let i = 0;
const n = text.length;
while (i < n) {
let j = i;
while (j < n && text[j] === text[i]) {
++j;
}
const l = j - i;
let k = j + 1;
while (k < n && text[k] === text[i]) {
++k;
}
const r = k - j - 1;
ans = Math.max(ans, Math.min(cnt[idx(text[i])], l + r + 1));
i = j;
}
return ans;
}
|