🚩 题目链接
⛲ 题目描述
给你一个仅由小写英文字母组成的字符串 s 。
如果一个字符串仅由单一字符组成,那么它被称为 特殊 字符串。例如,字符串 “abc” 不是特殊字符串,而字符串 “ddd”、“zz” 和 “f” 是特殊字符串。
返回在 s 中出现 至少三次 的 最长特殊子字符串 的长度,如果不存在出现至少三次的特殊子字符串,则返回 -1 。
子字符串 是字符串中的一个连续 非空 字符序列。
示例 1:
输入:s = “aaaa”
输出:2
解释:出现三次的最长特殊子字符串是 “aa” :子字符串 “aaaa”、“aaaa” 和 “aaaa”。
可以证明最大长度是 2 。
示例 2:
输入:s = “abcdef”
输出:-1
解释:不存在出现至少三次的特殊子字符串。因此返回 -1 。
示例 3:
输入:s = “abcaba”
输出:1
解释:出现三次的最长特殊子字符串是 “a” :子字符串 “abcaba”、“abcaba” 和 “abcaba”。
可以证明最大长度是 1 。
提示:
3 <= s.length <= 5 * 105
s 仅由小写英文字母组成。
🌟 求解思路&实现代码&运行结果
⚡ 二分 + 滑动窗口
🥦 求解思路
- 为了找到在 s 中出现 至少三次 的 最长特殊子字符串 的长度,该题目我们可以通过二分和滑动窗口的思想来做,首先通过二分去找当前长度的字符串是否可以满足至少出现3次,具体怎么判断呢?
- 可以继续通过滑动窗口来实现。每次判断时,指针不回退,相等继续向后判断,统计当前相等的字符出现的次数,如果大于等于3,二分的左边界向右移,否则,右边界左移。
- 有了基本的思路,接下来我们就来通过代码来实现一下。
🥦 实现代码
class Solution {
private String s;
private int n;
public int maximumLength(String s) {
this.s = s;
this.n = s.length();
int left = -1, right = n + 1;
while (left + 1 < right) {
int mid = (left + right) >> 1;
if (check(mid)) {
left = mid;
} else {
right = mid;
}
}
return left == 0 ? -1 : left;
}
// 检查长度为x的字符串出现的次数是否至少3次
public boolean check(int x) {
int[] cnt = new int[26];
for (int i = 0; i < n;) {
int next = i + 1;
while (next < n && s.charAt(next) == s.charAt(i)) {
next++;
}
int k = s.charAt(i) - 'a';
cnt[k] += Math.max(0, next - i - x + 1);
if (cnt[k] >= 3) {
return true;
}
i = next;
}
return false;
}
}