有效的字母异位词

标签: 哈希表 字符串 排序

难度: Easy

给定两个字符串 st ,编写一个函数来判断 t 是否是 s 的字母异位词。

注意:若 st 中每个字符出现的次数都相同,则称 st 互为字母异位词。

 

示例 1:

输入: s = "anagram", t = "nagaram"
输出: true

示例 2:

输入: s = "rat", t = "car"
输出: false

 

提示:

  • 1 <= s.length, t.length <= 5 * 104
  • st 仅包含小写字母

 

进阶: 如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?

Submission

运行时间: 19 ms

内存: 16.1 MB

class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        lst1 = sorted(set(s))
        lst2 = sorted(set(t))
        if len(lst1) != len(lst2):return False
        for item in range(len(lst1)):
            if s.count(lst1[item]) != t.count(lst1[item]):
                return False
        return True

Explain

这个题解的思路是先对两个字符串 s 和 t 分别做去重排序,得到两个字符集合 lst1 和 lst2。如果两个集合长度不同,直接返回 False。然后遍历其中一个集合,比较每个字符在原字符串 s 和 t 中出现的次数,如果次数不同则返回 False,否则遍历结束后返回 True。

时间复杂度: O(nlogn)

空间复杂度: O(n)

class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        # 对两个字符串分别去重并排序
        lst1 = sorted(set(s))
        lst2 = sorted(set(t))
        
        # 如果两个字符集合长度不等,直接返回 False
        if len(lst1) != len(lst2):
            return False
        
        # 遍历字符集合
        for item in range(len(lst1)):
            # 比较当前字符在两个原字符串中出现的次数
            if s.count(lst1[item]) != t.count(lst1[item]):
                return False
        
        # 遍历结束没有返回 False,说明是字母异位词,返回 True
        return True

Explore

排序的方法是一种直观且容易理解的方法来检查两个字符串是否为字母异位词,因为它将字符串重组为标准形式,使比较变得简单。然而,这种方法的时间复杂度通常是O(n log n),主要由排序操作决定。在字符串非常长或需要高效处理大量数据的情况下,这可能不是最优的。更高效的方法可能是使用哈希表来统计每个字符出现的次数,这样的时间复杂度可以降低到O(n)。

在这个题解中,使用`sorted(set(s))`去重后再排序是不必要的,且实际上会影响到判断的准确性。因为字母异位词的定义是两个字符串包含相同的字符,每个字符出现的次数也相同,而去重将丢失字符出现的次数信息。正确的做法应该是直接对整个字符串进行排序,然后比较排序后的字符串是否完全相同。

如果字符串包含Unicode字符,现有的方法理论上仍然适用,因为排序和计数函数通常支持Unicode字符。然而,如果涉及特殊的Unicode字符(如组合字符或变音符号),可能需要额外处理来正确比较。在这种情况下,可以考虑使用Unicode正规化,确保每个字符以相同方式表示,再进行排序或统计字符频率。

在题解中选择遍历排序后的字符集合主要是为了确保只比较两个字符串共有的字符。这种方法可以减少一些不必要的比较(例如,如果一个字符在一个字符串中不存在,则不需要检查它在另一个字符串中的出现次数)。然而,这种方法在去重后实际上造成了信息丢失,不应在处理字母异位词时使用。更合理的做法是直接对整个字符串进行字符频率统计,然后比较两个字符串中各字符的频率是否完全相同。