返回
创建于
状态公开
详细的例子和推理来解释「所有子字符串中的元音」这道题的高效做法。
问题本质
给定一个字符串 word,你需要返回所有子字符串中元音('a', 'e', 'i', 'o', 'u')出现的总次数。
注意:不是统计不同子串的元音数,而是所有子串中元音出现的总和,即每个元音在所有包含它的子串中都要计数。
直观但低效的做法
最直接的思路是:
- 枚举所有子串
- 对每个子串统计元音数并累加
但这样复杂度是 (枚举子串 ,每个子串统计元音 ),对于长字符串会超时。
高效做法的核心思想
每个元音在所有包含它的子串中会被重复计数多次。我们可以直接计算每个元音在多少个子串中出现,然后累加。
数学推导
假设字符串长度为 ,元音出现在下标 (从0开始)。
- 以 结尾的子串有 个(起点可以是0到i)
- 以 为起点的子串有 个(终点可以是i到n-1)
所以包含下标 的所有子串数量是 。
举例说明:
假设字符串是 "abcde",长度为5。
- 下标0的字符'a',出现在 个子串里
- 下标4的字符'e',出现在 个子串里
实现步骤
- 初始化总数为0。
- 遍历字符串的每个字符及其下标。
- 如果是元音,计算它的贡献 并加到总数上。
- 遍历结束后返回总数。
代码(Go语言)
1func countVowels(word string) int64 {
2 n := len(word)
3 var total int64 = 0
4 vowels := map[byte]bool{'a': true, 'e': true, 'i': true, 'o': true, 'u': true}
5 for i := 0; i < n; i++ {
6 if vowels[word[i]] {
7 total += int64(i+1) * int64(n-i)
8 }
9 }
10 return total
11}例子详细推演
以 word = "aba" 为例:
- 长度 n = 3
- 下标0: 'a',是元音,贡献 = (0+1)*(3-0)=3
- 下标1: 'b',不是元音,贡献=0
- 下标2: 'a',是元音,贡献 = (2+1)*(3-2)=3
总和 = 3 + 0 + 3 = 6
所有子串及元音数如下:
- "a":1
- "ab":1
- "aba":2
- "b":0
- "ba":1
- "a":1 总和 = 1+1+2+0+1+1 = 6
和公式计算一致。
总结
- 每个元音出现的次数 = (下标+1) * (总长-下标)
- 只需遍历一次字符串,时间复杂度 O(n),空间 O(1)
- 适合大数据量场景