📌 题目链接:242. 有效的字母异位词
题目描述
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
示例 1:
输入: s = "anagram", t = "nagaram" 输出: true
示例 2:
输入: s = "rat", t = "car" 输出: false
说明: 你可以假设字符串只包含小写字母。
思路分析
1. 暴力解法
最直接的思路是双层 for 循环,每次从 s 中取出一个字符去 t 里找是否存在。
这种方法不仅需要额外标记字符是否用过,还会导致时间复杂度达到 O(n^2),在字符串很长时效率极低。
因此,我们考虑更优的解法。
2. 哈希表解法
为什么用哈希表(数组)?
-
本题的关键在于 统计两个字符串中每个字符出现的次数。
-
我们需要快速完成 字符 → 出现次数 的映射。
-
哈希表(数组)正好适合这种场景。
为什么用数组代替哈希表?
-
因为题目限定了只包含小写字母
'a' ~ 'z',刚好 26 个字母。 -
我们可以用一个长度为
26的数组record来代替哈希表,效率更高。 -
而Hashmap虽然通用性好,但是针对有限少量数据的数据结构,代码实现复杂度较高,不如用哈希表数组实现。
-
record[i]表示某个字母出现的次数,其中:-
record[s.charAt(i) - 'a']++统计字符串s -
record[t.charAt(i) - 'a']--抵消字符串t
-
最后只要判断 record 中是否所有值都为 0,即可确定两个字符串是否为字母异位词。
动画理解
假设 s = "aee", t = "eae"
-
遍历
s:-
a→record[0]++ -
e→record[4]++ -
e→record[4]++
此时record[0] = 1, record[4] = 2
-
-
遍历
t:-
e→record[4]-- -
a→record[0]-- -
e→record[4]--
此时record[0] = 0, record[4] = 0
-
最终 record 数组全为 0,说明 s 和 t 是异位词。
代码实现(Java)
class Solution {
public boolean isAnagram(String s, String t) {
// 长度不同直接返回 false
if (s.length() != t.length()) return false;
int[] record = new int[26];
// 一边统计 s,一边抵消 t
for (int i = 0; i < s.length(); i++) {
record[s.charAt(i) - 'a']++;
record[t.charAt(i) - 'a']--;
}
// 检查所有字母出现次数是否归零
for (int i = 0; i < 26; i++) {
if (record[i] != 0) return false;
}
return true;
}
}
复杂度分析
-
时间复杂度:O(n),其中 n 为字符串长度。只需一次遍历即可。
-
空间复杂度:O(1),只使用了固定大小的数组
record[26]。
方法对比
| 方法 | 思路 | 时间复杂度 | 空间复杂度 | 备注 |
|---|---|---|---|---|
| 暴力 | 双层循环,逐个匹配 | O(n^2) | O(1) | 超时不可取 |
| 排序 | 排序后比较两个字符串 | O(n log n) | O(1) | 简单但不够高效 |
| 哈希表 Map | 用 HashMap 统计频次 | O(n) | O(字符集大小) | 通用性好 |
| 数组代替哈希表 ✅ | 26 长度数组统计频次 | O(n) | O(1) | 本题最佳方案 |
1090

被折叠的 条评论
为什么被折叠?



