# 395. Longest Substring with At Least K Repeating Characters

**<font color=red>难度: Medium</font>**

## 刷题内容

> 原题连接

* https://leetcode.com/problems/longest-substring-with-at-least-k-repeating-characters/

> 内容描述

```
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.
```

## 解题方案

> 思路 1
******- 时间复杂度: O(N)******- 空间复杂度: O(N)******


因为一共就只有26种不同的英文字母字符，所以我们只要做26次遍历即可。
- 第1次找到一个最长的substring，它里面只有1种不同的字符，并且这1种字符出现至少k次
- 第2次找到一个最长的substring，它里面只有2种不同的字符，并且这2种字符都出现至少k次
- 第3次找到一个最长的substring，它里面只有2种不同的字符，并且这2种字符都出现至少k次
- 第4次找到一个最长的substring，它里面只有2种不同的字符，并且这2种字符都出现至少k次
- .........................................................................
- .........................................................................
- .........................................................................
- 第26次找到一个最长的substring，它里面只有26种不同的字符，并且这26种字符都出现至少k次

然后我们最终取最长的那个长度就可以了，大体就是slide window的思想，beats 15.57%

```python
class Solution(object):
    def longestSubstring(self, s, k):
        """
        :type s: str
        :type k: int
        :rtype: int
        """
        if k == 0 or len(s) == 0:
            return len(s)
        res = 0
        for ucc in range(1, 27):
            res = max(res, self.longestSubstringWithUcc(s, k, ucc))
        return res
    
    def longestSubstringWithUcc(self, s, k, ucc): # ucc: unique_chr_cnt
        count = collections.defaultdict(int)
        unique, no_less_than_k, start, res = 0, 0, 0, 0
        for i, c in enumerate(s):
            count[c] += 1
            if count[c] == 1:
                unique += 1
            if count[c] == k:
                no_less_than_k += 1
            while start <= i and unique > ucc:
                if count[s[start]] == 1:
                    unique -= 1
                if count[s[start]] == k:
                    no_less_than_k -= 1
                count[s[start]] -= 1
                start += 1
            if unique == ucc and no_less_than_k == ucc:
                res = max(res, i - start + 1)
        return res
```




> 思路 2
******- 时间复杂度: O(N)******- 空间复杂度: O(N)******

还有一个更好的方法，就是我们可以先计算出s中每种字符的个数，然后如果有一个字符的出现次数少于k次，那么说明任何包含这个字符的substring都不满足要求

因此我们可以用这个字符来split整个字符串s，然后对split出来的各个substring继续递归调用longestSubstring函数即可，返回其中的最大值。

如果所有的字符出现次数都不小于k次，那么说明整个字符串s都满足，我们直接返回len(s)

beats 32.51%

```python
class Solution(object):
    def longestSubstring(self, s, k):
        """
        :type s: str
        :type k: int
        :rtype: int
        """
        lookup = collections.Counter(s)
        for c in lookup:
            if lookup[c] < k:
                return max(self.longestSubstring(t, k) for t in s.split(c))
        return len(s)
```





























