395 Longest Substring with At Least K Repeating Characters

明白了写一下
https://www.youtube.com/watch?v=ti0kjxUdvzA&t=59s

https://leetcode.com/problems/longest-substring-with-at-least-k-repeating-characters/discuss/87739/Java-Strict-O(N)-Two-Pointer-Solution




The algorithm explanation: find sub strings with only 1 kind of letter that repeated at least k times. then find the sub string with 2 kind of letters that repeated at least k times. ... find sub string with all 26 kind of letters that repeated at least k times.
For each loop, it first check if the different letters exceeds current loop requirement, if so, keep getting rid of the last char of current sub string until the number of different letters reduced to current loop limit. When not exceed limit continue the iteration, and when the sub string matches the at least repeat k times condition, update max.
It may look stupid, but it's actually O(N) time complexity.


For h=1:26, we are going to use sliding window (left i, right j) to find the "longest window which contains exactly h unique characters and for each character, there are at least K repeating ones".
For example, when h=3, K=5, we are going to find the longest window contains exactly 3 unique characters and each repeating 5 times.


这个题走个例子会发现, 需要更新unique和 no less than k
因为每次判断就是 看下这两个满足条件吗




class Solution {
public int longestSubstring(String s, int k) {

int[] count = new int[26];
int h, i, j, idx, unique, noLessThanK; // not familiar with this
int max = 0;


for( h = 1; h <= 26; h++){
// need to reset the counts everytime we have a new h
Arrays.fill(count, 0); // not familair with this api
// reset everything for the new h
i = 0;
j = 0;
unique = 0;
noLessThanK = 0;
while(j < s.length()){

// condition to move j
if(unique <= h){
char current = s.charAt(j);
idx = current - 'a';
if(count[idx] == 0){
unique++;
}
count[idx]++;

if(count[idx] == k){
noLessThanK++;
}
j++;

}else{
// move i
// when there is more than h unique chars
char current = s.charAt(i);
idx = current - 'a';
if(count[idx] == k){
noLessThanK--;
}
if(count[idx] == 1){
unique--;
}
count[idx]--;
i++;
}
if(unique == h && unique == noLessThanK){
max = Math.max(max, j - i);
}
}
}

return max;
}
}





class Solution {
public int longestSubstring(String s, int k) {
// so many primitive vars , so declare here
int unique, noLessThanK, i, j, h;
int max = 0;
int[] count = new int[26];


// 1 unique chars, 2 unique chars, ... 26 unique chars
for(h = 1; h < 26; h++){
// reset all the vars for a new h
// count is used to recoding the freq of each char
Arrays.fill(count, 0);
unique = 0;
noLessThanK = 0;
i = 0;
j = 0;

while(j < s.length()){
// move j if unique char so far is <= h
if(unique <= h){
char current = s.charAt(j);
int index = current - 'a';
if(count[index] == 0){
unique++;
}
count[index]++;
if(count[index] == k){
noLessThanK++;
}
// rememerb j++
j++;
}else{
// we need to move i pointer
// when the unique char so far exceeds h
char current = s.charAt(i);
int index = current - 'a';
if(count[index] == k){
noLessThanK--;
}
count[index]--;
if(count[index] == 0){
unique--;
}
// remember i++
i++;
}

// if we found a string satisfies the condition
if(unique == h && noLessThanK == h){
max = Math.max(max, j - i);
}
}
}
return max;
}
}


 

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.

Example 1:

Input:
s = "aaabb", k = 3

Output:
3

The longest substring is "aaa", as 'a' is repeated 3 times.


 

Example 2:

Input:
s = "ababbc", k = 2

Output:
5

The longest substring is "ababb", as 'a' is repeated 2 times and 'b' is repeated 3 times.