一、Problem
Find the length of the longest substring T of a given string (consists of lowercase letters only) such that every character in T appears no less than k times.
Input:
s = "aaabb", k = 3
Output:
3
The longest substring is "aaa", as 'a' is repeated 3 times.
二、Solution
方法一:滑動窗口
- 窗口的含義
- 囊括所有頻次 >= k 的字符
- 窗口右移時機
- 每次都右移
- 窗口左移時機
- 當窗口出現頻次 < k 的字符
- 結算時機
- 當遇到頻次 < k 的字符 s[i],則遞歸求解 左側字符串的合法序列長度和 右側字符串的合法序列長度
class Solution {
int div(char[] s, int l, int r, int k) {
int[] freq = new int[258];
for (int i = l; i < r; i++) freq[s[i]]++;
for (int i = l; i < r; i++) {
if (freq[s[i]] < k) {
int len1 = div(s, l, i, k);
int len2 = div(s, i+1, r, k);
return Math.max(len1, len2);
}
}
return r-l;
}
public int longestSubstring(String s, int k) {
return div(s.toCharArray(), 0, s.length(), k);
}
}
複雜度分析
- 時間複雜度:,
- 空間複雜度:,
方法二:分治優化
優化:如果 位置存在是一段長度爲 len 的都是不合法的子串,那麼在方法一中一定會在那裏調用 len 次 div 方法,這是不必要的。所以基於這個問題,我們可以想方法優化。在 的左邊出現同樣情況也同理。
class Solution {
int div(char[] s, int l, int r, int k) {
int[] freq = new int[258];
for (int i = l; i <= r; i++) freq[s[i]]++;
while (l < r && freq[s[l]] < k) l++;
while (l < r && freq[s[r]] < k) r--;
for (int i = l; i <= r; i++) {
if (freq[s[i]] < k) {
int l1 = div(s, l, i-1, k);
int l2 = div(s, i+1, r, k);
return Math.max(l1, l2);
}
}
return r-l+1;
}
public int longestSubstring(String s, int k) {
return div(s.toCharArray(), 0, s.length()-1, k);
}
}
複雜度分析
- 時間複雜度:,
- 空間複雜度:,