Given a string s
and an integer k
, return the length of the longest substring of s
such that the frequency of each character in this substring is greater than or equal to k
.
Example 1:
Input: s = "aaabb", k = 3 Output: 3 Explanation: The longest substring is "aaa", as 'a' is repeated 3 times.
Example 2:
Input: s = "ababbc", k = 2 Output: 5 Explanation: The longest substring is "ababb", as 'a' is repeated 2 times and 'b' is repeated 3 times.
Constraints:
1 <= s.length <= 104
s
consists of only lowercase English letters.1 <= k <= 105
至少有K个重复字符的最长子串。
找到给定字符串(由小写字符组成)中的最长子串 T , 要求 T 中的每一字符出现次数都不少于 k 。输出 T 的长度。
这道题我提供一个滑动窗口的思路。首先暴力解就是以一个 O(n^2) 的复杂度去遍历input字符串,看看字符串中是否存在一个 [s.charAt(j), s.charAt(i)] 的子串满足题意。这个做法会超时。这道题还有分治的思路,但是我个人觉得不是很好想所以这里不列出了。
这里我们把题目要求拆分一下。既然题目说了只有小写字母(这里我非常怀疑,因为用数组统计的时候如果数组长度只创建成26是会越界的),那么我们可以从1到26去试探。这里我们试探的是找一个子串,其中包含了一个,两个,三个或者。。26个不同字符,每个字符出现次数不少于K。这样一来我们就可以把题目转化成类似159和340那样的做法了。
时间O(n)
空间O(n)
Java实现
1 class Solution { 2 public int longestSubstring(String s, int k) { 3 int res = 0; 4 // 试探input字符串中是否能找到一个最长的字符串,存在有numUniqueTarget个不同字符 5 // 我们这里是从1 - 26一个个去试探 6 for (int numUniqueTarget = 1; numUniqueTarget <= 26; numUniqueTarget++) { 7 res = Math.max(res, helper(s, k, numUniqueTarget)); 8 } 9 return res; 10 } 11 12 // sliding window模板 13 private int helper(String s, int k, int i) { 14 int[] map = new int[256]; 15 int start = 0; 16 int end = 0; 17 int res = Integer.MIN_VALUE; 18 // 子串内unique的字母个数 19 int counter = 0; 20 // 出现次数不少于K的字母个数 21 int numNoLessThanK = 0; 22 while (end < s.length()) { 23 char c1 = s.charAt(end); 24 if (map[c1]++ == 0) { 25 counter++; 26 } 27 if (map[c1] == k) { 28 numNoLessThanK++; 29 } 30 end++; 31 32 while (counter > i) { 33 char c2 = s.charAt(start); 34 if (map[c2]-- == k) { 35 numNoLessThanK--; 36 } 37 if (map[c2] == 0) { 38 counter--; 39 } 40 start++; 41 } 42 43 if (counter == numNoLessThanK) { 44 res = Math.max(res, end - start); 45 } 46 } 47 return res; 48 } 49 }