leetcode
leetcode 1201 ~ 1250
子串的最大出现次数

子串的最大出现次数

难度:

标签:

题目描述

代码结果

运行时间: 95 ms, 内存: 0.0 MB


/*
 * 思路:
 * 1. 使用Java Stream来遍历字符串并生成所有可能的子串。
 * 2. 对每个子串进行过滤,保留满足条件的子串。
 * 3. 使用Collectors.groupingBy和Collectors.counting来统计每个子串的出现次数。
 * 4. 返回出现次数最多的子串的次数。
 */
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class SolutionStream {
    public int maxFreq(String s, int maxLetters, int minSize, int maxSize) {
        Map<String, Long> substringCount = IntStream.range(0, s.length() - minSize + 1)
            .mapToObj(i -> s.substring(i, i + minSize))
            .filter(sub -> isValid(sub, maxLetters))
            .collect(Collectors.groupingBy(sub -> sub, Collectors.counting()));
        return substringCount.values().stream().mapToInt(Long::intValue).max().orElse(0);
    }

    private boolean isValid(String sub, int maxLetters) {
        long uniqueCount = sub.chars().distinct().count();
        return uniqueCount <= maxLetters;
    }
}

解释

方法:

题解的核心思路是先考虑最小子串长度 `minSize`,因为较小的子串更可能在字符串中重复出现。首先,使用一个滑动窗口的方法生成所有长度为 `minSize` 的子串,并利用 `collections.Counter` 统计这些子串的出现频率。随后,遍历这个频率字典,选出那些满足“子串中不同字母的数目不超过 `maxLetters`”的子串,并记录它们的最大出现次数。这种方法避免了考虑 `maxSize`,因为更长的子串出现次数通常不会超过最小长度子串的出现次数。

时间复杂度:

O(n * minSize)

空间复杂度:

O(n)

代码细节讲解

🦆
在题解中提到使用滑动窗口生成所有长度为 `minSize` 的子串,为什么不需要同时考虑 `maxSize` 的子串呢?
在处理子串的最大出现次数时,选择 `minSize` 的原因是基于统计的观察,即更短的子串更有可能在字符串中频繁出现。由于任何长度大于 `minSize` 且小于或等于 `maxSize` 的子串包含了长度为 `minSize` 的子串,如果 `minSize` 子串的出现频率已不高,其包含的更长子串的出现频率自然也不会更高。因此,直接分析 `minSize` 长度的子串足以找到可能的最大频率,无需额外计算更长子串的频率,从而提高算法的效率。
🦆
题解中使用 `collections.Counter` 统计子串出现频率时,是否考虑了字符串中的重叠子串?如果有,这对结果有何影响?
是的,使用 `collections.Counter` 统计子串时,考虑了字符串中的重叠子串。这意味着每一个可能的子串位置都被生成并计数,包括那些起始索引相邻的重叠子串。这种方法确保了所有可能的子串都被计算在内,从而可以准确地找到出现频率最高的子串。对结果的影响是使得计算更全面,但也意味着计算量增大,尤其是在字符串较长时。
🦆
为什么题解中最终选择返回 `max([count[w] for w in count if len(set(w)) <= maxLetters] + [0])`,而不是直接从计数器中获取最大值?
这样做是为了确保只考虑那些符合“子串中不同字母的数量不超过 `maxLetters`”的条件的子串。直接从计数器中获取最大值可能包括了不符合字母数量条件的子串,导致结果不正确。通过添加 `[0]`,还能处理所有子串都不符合条件时的情况,此时函数可以安全返回 `0` 作为结果,避免在空列表上调用 `max` 函数导致错误。
🦆
当 `minSize` 接近于字符串 `s` 的长度时,这种算法的效率如何?是否存在更优化的处理方式?
当 `minSize` 接近于字符串 `s` 的长度时,滑动窗口的生成子串的操作变得较少,因为可以生成的子串数量减少(接近于 `len(s) - minSize + 1`)。在这种情况下,算法的效率相对较高,因为处理的数据量减少了。然而,如果 `minSize` 等于 `s` 的长度,那么只需要考虑整个字符串作为子串的情况,这可以进一步简化为直接计算字符串是否满足 `maxLetters` 条件并返回1或0。

相关问题