检查是否所有字符出现次数相同

标签: 哈希表 字符串 计数

难度: Easy

给你一个字符串 s ,如果 s 是一个  字符串,请你返回 true ,否则请返回 false 。

如果 s 中出现过的 所有 字符的出现次数 相同 ,那么我们称字符串 s 是  字符串。

 

示例 1:

输入:s = "abacbc"
输出:true
解释:s 中出现过的字符为 'a','b' 和 'c' 。s 中所有字符均出现 2 次。

示例 2:

输入:s = "aaabb"
输出:false
解释:s 中出现过的字符为 'a' 和 'b' 。
'a' 出现了 3 次,'b' 出现了 2 次,两者出现次数不同。

 

提示:

  • 1 <= s.length <= 1000
  • s 只包含小写英文字母。

Submission

运行时间: 23 ms

内存: 15.9 MB

class Solution:
    def areOccurrencesEqual(self, s: str) -> bool:
        counts = {}
        for c in s:
            if c not in counts:
                counts[c] = 0
            counts[c] += 1
        v = counts.values()
        return min(v) == max(v)

Explain

此题解的核心思想是使用哈希表来统计每个字符在字符串中出现的次数。首先,遍历字符串,对于每个字符,如果它不在哈希表中,则将其加入哈希表,并初始化其计数为0。随后,每次遇到该字符时,都将其对应的计数增加1。完成遍历后,我们得到了一个完整的字符频率表。最后,通过比较哈希表中的最小值和最大值来判断所有字符的出现次数是否相同。如果最小和最大值相等,则说明所有字符出现的次数相同,返回true;否则返回false。

时间复杂度: O(n)

空间复杂度: O(1)

# 定义一个解决问题的类

class Solution:
    def areOccurrencesEqual(self, s: str) -> bool:
        counts = {}  # 创建一个字典用于存储每个字符的出现次数
        for c in s:  # 遍历字符串中的每个字符
            if c not in counts:  # 如果字符不在字典中,初始化计数为0
                counts[c] = 0
            counts[c] += 1  # 增加该字符的计数
        v = counts.values()  # 获取字典中所有计数的值
        return min(v) == max(v)  # 如果最小计数和最大计数相等,则返回true,否则返回false

Explore

在题解中,初始化计数为0似乎是一个错误。实际上,当一个字符第一次出现时,应该初始化其计数为1。初始化为0并立即在遍历中将其增加到1,这是一种编程上的处理方式,用以保持代码的一致性,即先检查后增加。正确的做法应该是直接将未在字典中的字符计数初始化为1。

在提供的代码中,如果输入字符串是空的,那么`counts`字典也将是空的。在这种情况下,调用`min(v)`和`max(v)`会抛出`ValueError`,因为这两个方法不能在空集合上调用。因此,代码应该在尝试获取最小值和最大值前,先检查`v`是否为空。如果为空,则可以直接返回`True`,因为一个空字符串可以被认为是所有字符出现次数相等的(都是0次)。

比较最小计数和最大计数是一种直观且效率高的方法来确认所有字符的出现次数是否相同。只有当所有计数相等时,最小值和最大值才会相等。另一种方法是使用集合来检查所有值是否相同,即通过将计数值转换为集合,如果集合的大小为1,则意味着所有计数相同。例如,可以使用 `len(set(counts.values())) == 1` 来实现这一点。这种方法同样有效,但在某些情况下可能稍微慢一些,因为需要构造一个集合。

给定的算法可以处理包含任意数量字符的字符串,包括所有26个英文字母的情况。算法的时间复杂度主要取决于字符串的长度,因为每个字符都要被检查和统计。在极端情况下,即使每个字母的出现频率极不相同,该算法仍然可以正确地统计出每个字符的出现次数并进行比较。性能主要受字符串长度的影响,而不是字符种类或其出现频率的差异。