在问 · 算法题解

242. 有效的字母异位词

简单字符串计数数组力扣原题 ↗

题目描述

输入两个字符串 s 和 t。

如果 t 只是把 s 的字母换了个顺序,也就是两者用到的每个字母及其个数都相同,就称 t 是 s 的字母异位词。

是字母异位词时返回 true,否则返回 false。

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

解释:两个字符串都由 3 个 a、1 个 n、1 个 g、1 个 r、1 个 m 组成。

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

解释:s 里有字母 t,t 里没有;t 里有字母 c,s 里没有。

数据范围

  • 1 <= s.length, t.length <= 5 * 10^4
  • s 和 t 只由小写英文字母组成。

进阶:如果字符串中可能出现 Unicode 字符,你的做法要怎样调整?

解题思路:计数数组

长度不同直接返回 false。否则用长度 26 的计数数组:扫 s 时每个字母 +1,再扫 t 时每个字母 -1。一旦某个计数变成负数,说明 t 里这个字母比 s 多,返回 false。长度相同又没有负数,就说明所有计数恰好归 0。

为什么正确

扫过 t 的前 j 个字母后,cnt[c] = s 中 c 的个数 − t[:j] 中 c 的个数。

复杂度分析

时间 O(n);空间 O(26)。

易错点

别忘了先比较长度:只检查“不出现负数”时,t 比 s 短(如 s="ab", t="a")也会被误判为 true。

参考代码

Python、Java、C++、Go、JavaScript、TypeScript 六种语言,逻辑一致。

class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        if len(s) != len(t):
            return False
        cnt = [0] * 26
        for ch in s:
            cnt[ord(ch) - ord('a')] += 1
        for ch in t:
            cnt[ord(ch) - ord('a')] -= 1
            if cnt[ord(ch) - ord('a')] < 0:
                return False
        return True

载入编辑器,自己跑一遍 →

其他解法

排序后比较最简洁,但要 O(n log n);计数数组利用字符集只有 26 个小写字母,线性时间完成。

解法 2:排序后比较 时间 O(n log n),空间 O(n)

两个字符串互为字母异位词,当且仅当把各自的字符排序后得到的字符串相同。分别排序后直接比较。

一两行就能写完,不依赖字符集大小,输入含 Unicode 字符时也能直接用。排序是 O(n log n),比计数慢。

class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        return sorted(s) == sorted(t)

字符串 专题的其他题目

查看 字符串 全部题目 →