统计完全子字符串
难度:
标签:
题目描述
You are given a string word
and an integer k
.
A substring s
of word
is complete if:
- Each character in
s
occurs exactlyk
times. - The difference between two adjacent characters is at most
2
. That is, for any two adjacent charactersc1
andc2
ins
, the absolute difference in their positions in the alphabet is at most2
.
Return the number of complete substrings of word
.
A substring is a non-empty contiguous sequence of characters in a string.
Example 1:
Input: word = "igigee", k = 2 Output: 3 Explanation: The complete substrings where each character appears exactly twice and the difference between adjacent characters is at most 2 are: igigee, igigee, igigee.
Example 2:
Input: word = "aaabbbccc", k = 3 Output: 6 Explanation: The complete substrings where each character appears exactly three times and the difference between adjacent characters is at most 2 are: aaabbbccc, aaabbbccc, aaabbbccc, aaabbbccc, aaabbbccc, aaabbbccc.
Constraints:
1 <= word.length <= 105
word
consists only of lowercase English letters.1 <= k <= word.length
代码结果
运行时间: 665 ms, 内存: 21.3 MB
/*
* Problem: Find the number of fully matching substrings in the given string `word` where each character appears exactly `k` times,
* and adjacent characters in the substring differ in their alphabetical positions by at most 2.
*
* Approach:
* 1. Generate all substrings using IntStream.
* 2. Use a frequency array to count the occurrences of each character in the substring.
* 3. Check if each character in the substring appears exactly `k` times.
* 4. Verify that the difference in the positions of adjacent characters is at most 2.
* 5. Count the valid substrings.
*/
import java.util.stream.IntStream;
public int countFullyMatchingSubstringsStream(String word, int k) {
int n = word.length();
return (int) IntStream.range(0, n).flatMap(i -> IntStream.range(i + 1, n + 1)
.mapToObj(j -> word.substring(i, j)))
.filter(s -> {
int[] freq = new int[26];
s.chars().forEach(c -> freq[c - 'a']++);
if (IntStream.of(freq).anyMatch(count -> count != 0 && count != k))
return false;
return IntStream.range(1, s.length()).allMatch(i -> Math.abs(s.charAt(i) - s.charAt(i - 1)) <= 2);
}).count();
}
解释
方法:
本题解采用了双指针法和哈希表来统计完全子字符串。首先,初始化一个长度为26的列表char_positions,用于存储每个字符在word中的出现位置。接着,遍历word中的每个字符,更新char_positions,并检查当前字符是否与前一个字符在字母表中的顺序相差超过2,如果是,则更新切割点cut。然后,检查当前字符出现的次数是否达到k次,如果达到,则调用check函数检查从pre(当前字符第k次出现的位置)到i(当前位置)的子字符串是否满足每个字符恰好出现k次的条件。如果满足,则增加答案计数器ans,并更新pre的位置,继续检查。最后,返回答案计数器ans。
时间复杂度:
O(n^2)
空间复杂度:
O(n)
代码细节讲解
🦆
在函数`check`中,为什么要单独处理当前字符出现次数不足k或超过k的情况,这与算法的哪些核心逻辑相关?
▷🦆
请问为什么需要在相邻字符的字母表顺序相差超过2时更新切割点cut,这样做的目的是什么?
▷🦆
在`countCompleteSubstrings`函数中,如何判断一个子字符串从pre到i是否满足每个字符恰好出现k次,具体是通过哪些步骤实现的?
▷