题目描述
给你一个字符串 s
,请找出满足每个字符最多出现两次的最长子字符串,并返回该子字符串的 最大 长度。
示例 1:
输入: s = "bcbbbcba"
输出: 4
解释:
以下子字符串长度为 4,并且每个字符最多出现两次:"bcbbbcba"
。
示例 2:
输入: s = "aaaa"
输出: 2
解释:
以下子字符串长度为 2,并且每个字符最多出现两次:"aaaa"
。
提示:
2 <= s.length <= 100
s
仅由小写英文字母组成。
解法
方法一:双指针
我们用两个指针 $i$ 和 $j$ 来维护一个滑动窗口,用一个数组 $cnt$ 来记录窗口中每个字符的出现次数。
每一次,我们将指针 $j$ 对应的字符 $c$ 加入窗口,然后判断 $cnt[c]$ 是否大于 $2$,如果大于 $2$,则将指针 $i$ 循环右移,直到 $cnt[c]$ 小于等于 $2$。此时,我们更新答案 $ans = \max(ans, j - i + 1)$。
最终,我们返回答案 $ans$。
时间复杂度 $O(n)$,其中 $n$ 为字符串 $s$ 的长度。空间复杂度 $O(|\Sigma|)$,其中 $\Sigma$ 为字符集,本题中 $\Sigma = 26$。
| class Solution:
def maximumLengthSubstring(self, s: str) -> int:
cnt = Counter()
ans = i = 0
for j, c in enumerate(s):
cnt[c] += 1
while cnt[c] > 2:
cnt[s[i]] -= 1
i += 1
ans = max(ans, j - i + 1)
return ans
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | class Solution {
public int maximumLengthSubstring(String s) {
int[] cnt = new int[26];
int ans = 0;
for (int i = 0, j = 0; j < s.length(); ++j) {
int idx = s.charAt(j) - 'a';
++cnt[idx];
while (cnt[idx] > 2) {
--cnt[s.charAt(i++) - 'a'];
}
ans = Math.max(ans, j - i + 1);
}
return ans;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | class Solution {
public:
int maximumLengthSubstring(string s) {
int cnt[26]{};
int ans = 0;
for (int i = 0, j = 0; j < s.length(); ++j) {
int idx = s[j] - 'a';
++cnt[idx];
while (cnt[idx] > 2) {
--cnt[s[i++] - 'a'];
}
ans = max(ans, j - i + 1);
}
return ans;
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | func maximumLengthSubstring(s string) (ans int) {
cnt := [26]int{}
i := 0
for j, c := range s {
idx := c - 'a'
cnt[idx]++
for cnt[idx] > 2 {
cnt[s[i]-'a']--
i++
}
ans = max(ans, j-i+1)
}
return
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13 | function maximumLengthSubstring(s: string): number {
let ans = 0;
const cnt: number[] = Array(26).fill(0);
for (let i = 0, j = 0; j < s.length; ++j) {
const idx = s[j].charCodeAt(0) - 'a'.charCodeAt(0);
++cnt[idx];
while (cnt[idx] > 2) {
--cnt[s[i++].charCodeAt(0) - 'a'.charCodeAt(0)];
}
ans = Math.max(ans, j - i + 1);
}
return ans;
}
|