至少有 K 个重复字符的最长子串
难度:
标签:
题目描述
给你一个字符串 s
和一个整数 k
,请你找出 s
中的最长子串, 要求该子串中的每一字符出现次数都不少于 k
。返回这一子串的长度。
如果不存在这样的子字符串,则返回 0。
示例 1:
输入:s = "aaabb", k = 3 输出:3 解释:最长子串为 "aaa" ,其中 'a' 重复了 3 次。
示例 2:
输入:s = "ababbc", k = 2 输出:5 解释:最长子串为 "ababb" ,其中 'a' 重复了 2 次, 'b' 重复了 3 次。
提示:
1 <= s.length <= 104
s
仅由小写英文字母组成1 <= k <= 105
代码结果
运行时间: 40 ms, 内存: 0.0 MB
/*
* 思路:
* 1. 使用Stream API实现递归方法。
* 2. 统计字符串中每个字符的出现次数。
* 3. 找到出现次数少于k次的字符作为分隔符,分割字符串。
* 4. 对每个子串递归调用函数,并返回满足条件的最长子串长度。
*/
import java.util.Map;
import java.util.stream.Collectors;
public class Solution {
public int longestSubstring(String s, int k) {
if (s == null || s.length() == 0 || k > s.length()) return 0;
return helper(s, k);
}
private int helper(String s, int k) {
if (s.length() < k) return 0;
Map<Character, Long> freq = s.chars()
.mapToObj(c -> (char) c)
.collect(Collectors.groupingBy(c -> c, Collectors.counting()));
for (char c : s.toCharArray()) {
if (freq.get(c) < k) {
return s.chars()
.mapToObj(i -> (char) i)
.collect(Collectors.joining())
.split(String.valueOf(c)).length;
}
}
return s.length();
}
}
解释
方法:
这个题解采用了分治的思想。首先将字符串 s 放入栈中。然后不断从栈中取出子串,统计每个字符出现的次数。如果所有字符出现次数都不小于 k,则更新目前为止找到的最长子串长度。否则,找到出现次数小于 k 的字符,以它为分隔符将子串分割成更短的子串,放入栈中继续处理。这样递归处理下去,直到栈为空,即可找到最长的满足条件的子串。
时间复杂度:
O(n^2)
空间复杂度:
O(n)
代码细节讲解
🦆
在分治方法中,为什么选择以出现次数小于k的字符为分隔符进行分割?
▷🦆
在题解中提到每个字符最多会被放入和弹出栈一次,这是否意味着每个子串只被处理一次?如果是这样,如何保证处理了所有可能的子串?
▷🦆
题解中使用栈来存储待处理的子串,是否可以使用其他数据结构如队列或链表来改善性能或逻辑清晰度?
▷🦆
在处理过程中,如果一个长字符串的多个位置字符频率都小于k,是否会导致重复分割和重复处理?如果会,如何优化以避免这种情况?
▷