题目大意:
子串的最大出现次数
给你一个字符串 s
,请你返回满足以下条件且出现次数最大的 任意 子串的出现次数:
- 子串中不同字母的数目必须小于等于
maxLetters
。 - 子串的长度必须大于等于
minSize
且小于等于maxSize
。
示例 1:
输入:s = "aababcaab", maxLetters = 2, minSize = 3, maxSize = 4 输出:2 解释:子串 "aab" 在原字符串中出现了 2 次。 它满足所有的要求:2 个不同的字母,长度为 3 (在 minSize 和 maxSize 范围内)。
示例 2:
输入:s = "aaaa", maxLetters = 1, minSize = 3, maxSize = 3 输出:2 解释:子串 "aaa" 在原字符串中出现了 2 次,且它们有重叠部分。
示例 3:
输入:s = "aabcabcab", maxLetters = 2, minSize = 2, maxSize = 3 输出:3
示例 4:
输入:s = "abcde", maxLetters = 2, minSize = 3, maxSize = 3 输出:0
提示:
- 1 <= s.length <= 10^5
- 1 <= maxLetters <= 26
- 1 <= minSize <= maxSize <= min(26, s.length)
- s 只包含小写英文字母。
如果想查看本题目是哪家公司的面试题,请参考以下免费链接: https://leetcode.jp/problemdetail.php?id=1297
解题思路分析:
说实话一开始就没有想到太好的解题思路,尝试了一下暴力解法,居然可以通过,并且效率还不算太低。暴力解即以单词的每一位为开头取出长度为 minSize 到 maxSize 的所有子串,如果子串中的字母种类个数小于等于 maxLetters ,则将该子串加入到map中计数,循环玩所有子串之后,找到map中计数最大的一个即是返回结果。暴力解的时间复杂度为:O(n*26),n为字符串长度。
为了精益求精,接下来我们需要对暴力解进行剪枝优化,优化的关键点在于 minSize 和 maxSize ,比如最小长度为2,最大长度为5时,对于字符串abbbb来说,ab,abb,abbb,abbbb都是合理子串,但我们只要找到第一个(最短的)合理子串即可。因为abbbb包含了ab,如果整个字符串中存在N个abbbb,那么肯定至少包含了N个ab,也就是说,较短的子串个数一定大于等于较长的子串个数。
实现代码:
public int maxFreq(String s, int maxLetters, int minSize, int maxSize) { // 统计每个子串出现的个数 Map<String, Integer> map = new HashMap<>(); int res=0; // 返回结果 // 以每一个index开头循环 for(int i=0;i<s.length();i++){ // 当前子串长度 int length=0; // 当前子串中字母种类个数 int letterCount=0; // 记录出现过的字母 boolean[] hasLetter = new boolean[26]; // 当前子串 StringBuilder sb = new StringBuilder(); // 循环所有以i开头的子串 for(int j=i;j<s.length();j++){ length++; // 子串长度加一 char c = s.charAt(j); // 当前字符 sb.append(c); // 当前子串 // 如果当前字符在当前子串中没有出现过 if(!hasLetter[c-'a']){ // 标记为出现过 hasLetter[c-'a']=true; // 字母种类个数加一 letterCount++; // 如果字母种类个数大于maxLetters,退出当前循环 if(letterCount>maxLetters) break; } // 当子串长度大于等于minSize时(满足条件的子串) if(length>=minSize){ // 更新当前子串出现的次数 int count = map.getOrDefault(sb.toString(),0)+1; map.put(sb.toString(), count); // 更新全局子串出现的最大次数 res=Math.max(res, count); // 找到当前最短子串后,可退出循环。原因参考上文分析 break; } // 如果子串长度等于最大长度,退出循环 if(length==maxSize) break; } } return res; }
本题解法执行时间为46ms。
Runtime: 46 ms, faster than 83.87% of Java online submissions for Maximum Number of Occurrences of a Substring.
Memory Usage: 40.7 MB, less than 100.00% of Java online submissions for Maximum Number of Occurrences of a Substring.
本网站文章均为原创内容,并可随意转载,但请标明本文链接如有任何疑问可在文章底部留言。为了防止恶意评论,本博客现已开启留言审核功能。但是博主会在后台第一时间看到您的留言,并会在第一时间对您的留言进行回复!欢迎交流!
本文链接: http://leetcode.jp/leetcode-1297-maximum-number-of-occurrences-of-a-substring-解题思路分析/