Count Vowels
给定一个由英文字母组成的字符串 s,返回其中元音字母的数量。元音字母包括小写或大写的 a、e、i、o 和 u。字母 y 不计入。
函数
- sstring
- 要扫描的英文字母字符串
- 返回值integer
- s 中元音字母的数量,包含大写和小写
约束条件
1 ≤ s.length ≤ 5 × 104s只包含英文字母(a到z,A到Z)。
示例
- 输入
- s = "Interview"
- 输出
- 4
- 解释
- 元音字母是
I、e、i和e。大写的I和小写字母一样计算,所以答案是 4。
- 输入
- s = "rhythm"
- 输出
- 0
- 解释
rhythm中没有a、e、i、o或uy 不在列表中,所以答案是 0。
进阶
你能否只读取一次字符串,并返回五个元音字母各自出现的次数?
提示
逐个打开提示,每个都会多透露一点。
逐个查看字符。什么样的字符是元音字母?大写会改变判断结果吗?
测试每个字符之前,先将其转换为小写。这样,你只需与 5 个字母进行比较,而不是 10 个。
将计数器设为 0。对于每个字符,将它转换为小写;如果它是
a、e、i、o或u,就将计数器加 1。
题解
用计数器读取字符串一次。将每个字符转换为小写,这样检查 5 个元音就能同时涵盖大小写。
分别遍历一次,统计每个元音
思路
对 aeiouAEIOU 中的十个字母分别遍历字符串并计数,然后把这十个计数相加。每个元音字母都恰好是这十个字母之一,因此只会被计数一次,而辅音字母都不属于这十个字母。
字符串会被读取十次。这仍然是 O(n),但对于 5 × 10^4 个字符来说,这意味着 5 × 10^5 次比较,因为每次遍历都会读取每个字符一次。
算法
- 将
total = 0。 - 依次取出这十个字母
aeiouAEIOU。 - 对于每个字母,遍历整个字符串,每当一个字符与它相等时,就将
total加 1。 - 完成十轮遍历后,返回
total。
def countVowels(s):
total = 0
for vowel in "aeiouAEIOU":
total += s.count(vowel) # one pass over s for this letter
return total一次遍历并检查小写
思路
读取字符串一次,并逐个判断其中的字符是否为元音。先将它转换为小写,会把 I 转换为 i,并让辅音仍然是辅音,这样你只需与 5 个字母比较,而不是 10 个。
检查所需的时间是常量:使用 switch、查找集合,或在字符串 aeiou 中搜索。每个字符只读取一次,并且只存储一个计数器:时间复杂度为 O(n),空间复杂度为 O(1)。
算法
- 将
count = 0。 - 逐个遍历字符串中的字符。
- 将字符转换为小写。
- 如果字符是
a、e、i、o或u,就将count加 1。 - 返回
count。
def countVowels(s):
vowels = set("aeiou")
count = 0
for ch in s:
if ch.lower() in vowels:
count += 1
return count
易错点和边界情况
- 只检查小写字母。仅与
aeiou比较会漏掉Interview中的大写字母I,并返回 3。 - 把
y也算进去。这里y从来不是元音,所以rhythm的结果是 0。 - 把索引 0 当成未匹配。
"aeiou".indexOf('a')的结果是 0,这表示匹配成功。要检查是否为-1;在 PHP 中,要用!==将strpos的结果与false比较,因为在 PHP 中0 == false。 - 在 C 的循环条件中调用
strlen(s)。它每一步都会重新扫描字符串,因此处理5 × 10^4个字符大约需要2.5 × 10^9步。
常见问题3
如何统计字符串中的元音字母?
用计数器遍历字符串一次。将每个字符转换为小写,如果它是 a、e、i、o 或 u,计数器就加 1。循环结束时,计数器中的值就是答案。
统计元音的时间复杂度是多少?
时间复杂度为 O(n),其中 n 是字符串的长度,因为每个字符都会与最多五个字母进行一次检查。额外空间复杂度为 O(1):一个计数器和固定的元音集合。
在这个问题中,y 是元音吗?
不算。在英语拼写中,y 有时会充当元音,例如 rhythm 中的 y。但编程题几乎总是将元音定义为 a、e、i、o 和 u,这道题也是如此。如果题目包含 y,就把它也加入你要检查的字母中。
相似题目
运用相同思路的题目。做两三道,才能真正掌握一种模式。
def countVowels(s):
# 在这里编写代码测试 #1
测试 #2
参数
s = "Interview"
预期输出
4