395. 至少有 K 个重复字符的最长子串(递归)

1. 题目

给你一个字符串 s 和一个整数 k ,请你找出 s 中的最长子串, 要求该子串中的每一字符出现次数都不少于 k 。返回这一子串的长度。

2. 示例

示例1:

输入:s = "aaabb", k = 3

输出:3

解释:最长子串为 "aaa" ,其中 'a' 重复了 3 次

示例2:

输入:s = "ababbc", k = 2

输出:5

解释:最长子串为 "ababb" ,其中 'a' 重复了 2 次, 'b' 重复了 3 次

3. 提示

  • 1 <= s.length <= 104

  • s 仅由小写英文字母组成

  • 1 <= k <= 105

4. 题解

我最开始看这题的时候,也跟在做的各位一样,毫无头绪;

看到连续子串,我的第一想法是滑动窗口,尝试过,不好做。

接着,发现里面暗含递归。

这道题的K很关键,我的第一想法都是想法将它作为递归条件。

就是某个字符在整个字符串里的个数小于k,此时将它划分为两半,左边用来递归,右边用来递归(分治+递归)。

但递归有始就有终。

开始的想法是,递归到最小子串时,此时只有两种可能就是:某个子串满足条件,此时不能再进行递归,子串的长度就是需要返回的值,还有一种,就不满足条件,此时子串的长度一定为0,也返回子串长度即可。

5. Code

 1 public class LongestSubstring {
 2     public int longestSubstring(String s, int k) {
 3         Map<Character, Integer> map = new HashMap<>();
 4         for(int i = 0; i < s.length(); i++) {
 5             if(map.containsKey(s.charAt(i))) {
 6                 map.put(s.charAt(i), map.get(s.charAt(i)) + 1);
 7             } else {
 8                 map.put(s.charAt(i), 1);
 9             }
10         }
11         int left = 0, right = 0;
12         while(left <= right && right < s.length()) {
13             if(map.get(s.charAt(right)) >= k) {
14                 right++;
15             } else {
16                 return Math.max(longestSubstring(s.substring(left, right), k), longestSubstring(s.substring(right+1), k));
17             }
18         }
19         return s.length();
20     }
21 
22     public static void main(String[] args) {
23         String s = "ababbc";
24         int k = 2;
25         System.out.println(new LongestSubstring().longestSubstring(s, k));
26     }
27 }
原文地址:https://www.cnblogs.com/haifwu/p/14821344.html