判断字符串的两半是否相似

标签: 字符串 计数

难度: Easy

给你一个偶数长度的字符串 s 。将其拆分成长度相同的两半,前一半为 a ,后一半为 b

两个字符串 相似 的前提是它们都含有相同数目的元音('a''e''i''o''u''A''E''I''O''U')。注意,s 可能同时含有大写和小写字母。

如果 a b 相似,返回 true ;否则,返回 false

示例 1:

输入:s = "book"
输出:true
解释:a = "bo" 且 b = "ok" 。a 中有 1 个元音,b 也有 1 个元音。所以,a 和 b 相似。

示例 2:

输入:s = "textbook"
输出:false
解释:a = "text" 且 b = "book" 。a 中有 1 个元音,b 中有 2 个元音。因此,a 和 b 不相似。
注意,元音 o 在 b 中出现两次,记为 2 个。

提示:

  • 2 <= s.length <= 1000
  • s.length 是偶数
  • s大写和小写 字母组成

Submission

运行时间: 23 ms

内存: 16.1 MB

class Solution:
    def halvesAreAlike(self, s: str) -> bool:
        vowels = set('aeiouAEIOU')
        mid = len(s) // 2
        a = s[:mid]
        b = s[mid:]
        count_a = sum(1 for c in a if c in vowels)
        count_b = sum(1 for c in b if c in vowels)
        return count_a == count_b

Explain

该题解首先创建一个包含所有元音字母的集合,以便高效地检查字符是否为元音。然后,它计算字符串s的中点,将字符串分为两半a和b。接着,分别计算两部分中的元音数量。最后,比较两部分的元音数量是否相等,如果相等则返回true,否则返回false。

时间复杂度: O(n)

空间复杂度: O(1)

class Solution:
    def halvesAreAlike(self, s: str) -> bool:
        vowels = set('aeiouAEIOU') # 创建元音字符集合
        mid = len(s) // 2 # 计算中点位置
        a = s[:mid] # 获取前半部分
        b = s[mid:] # 获取后半部分
        count_a = sum(1 for c in a if c in vowels) # 计算前半部分的元音数量
        count_b = sum(1 for c in b if c in vowels) # 计算后半部分的元音数量
        return count_a == count_b # 比较两部分的元音数量是否相等

Explore

在Python中,使用整数除法(//)计算中点时,如果字符串长度是奇数,中点计算结果将自动向下取整。这意味着,前半部分将比后半部分少一个字符。例如,对于长度为7的字符串,中点为3,前半部分包含0到2索引的字符(共3个),后半部分包含3到6索引的字符(共4个)。尽管两部分长度可能不完全相等,但这种方法仍然能有效地比较两部分中的元音数量,因为我们关注的是元音字符的数量而非总字符数量。

集合(set)在Python中是一个非常适合此类用途的数据结构,因为集合提供了高效的成员检查功能。集合的主要优势是其基于哈希表的实现,可以在平均情况下提供接近O(1)的时间复杂度进行元素查找,这比列表的O(n)时间复杂度要快得多。对于元音检查这样频繁的操作,使用集合可以极大地提升效率。

使用生成器表达式有几个优点。首先,它可以提供更简洁和更易于理解的代码,因为它将循环和条件检查合并为一行。其次,生成器表达式是惰性求值的,这意味着它只在需要时才计算每个元素,从而可以节省内存,特别是在处理大型数据集时。此外,生成器表达式直接与其他函数(如sum)结合使用时,可以避免额外的内存开销,因为不需要存储中间结果。

当前方法对于非常大的字符串来说,效率可能不是最优的,尤其是在必须遍历整个字符串两次(一次计算每个半部分的元音数)的情况下。一种更优化的方式可能包括单次遍历字符串,同时计算前半部分和后半部分的元音数。此外,如果字符串非常大,可以考虑使用并行处理方法或将字符串分解成块并在多个处理器上同时处理它们来进一步优化性能。