给你一个下标从 0 开始的字符串 s
,这个字符串只包含 0
到 9
的数字字符。
如果一个字符串 t
中至多有一对相邻字符是相等的,那么称这个字符串 t
是 半重复的 。例如,0010
、002020
、0123
、2002
和 54944
是半重复字符串,而 00101022
和 1101234883
不是。
请你返回 s
中最长 半重复 子字符串的长度。
一个 子字符串 是一个字符串中一段连续 非空 的字符。
示例 1:
输入:s = "52233" 输出:4 解释:最长半重复子字符串是 "5223" ,子字符串从 i = 0 开始,在 j = 3 处结束。
示例 2:
输入:s = "5494" 输出:4 解释:s 就是一个半重复字符串,所以答案为 4 。
示例 3:
输入:s = "1111111" 输出:2 解释:最长半重复子字符串是 "11" ,子字符串从 i = 0 开始,在 j = 1 处结束。
提示:
1 <= s.length <= 50
'0' <= s[i] <= '9'
提示 1
Since n is small, we can just check every substring, and if the substring is semi-repetitive, maximize the answer with its length.
解法:滑动窗口 (不定长)
class Solution {
public int longestSemiRepetitiveSubstring(String s) {
if (s.length() == 1) {
return 1;
}
int ans = Integer.MIN_VALUE;
// repeatCount记录窗口内 相邻且相等字符对的数量
int repeatCount = 0;
// repeatIndex记录窗口内 第一个 相邻且相等字符对的后一个字符的下标
int repeatIndex = -1;
int left = 0;
int right = 1;
while (right < s.length()) {
char c = s.charAt(right);
if (c == s.charAt(right - 1)) {
repeatCount++;
// 只记录窗口内 第一个 相邻且相等字符对的后一个字符的下标
if (repeatIndex == -1) {
repeatIndex = right;
}
}
// 窗口收缩,左边界右移
if (repeatCount > 1) {
left = repeatIndex;
repeatIndex = right;
repeatCount--;
}
ans = Math.max(ans, right - left + 1);
right++;
}
return ans;
}
}
复杂度分析
- 时间复杂度:O(n),n 是字符串 s 的长度。
- 空间复杂度:O(1)。