Easy
题目描述
给定两个字符串 s 和 t,编写一个函数来判断 t 是否是 s 的字母异位词。
**注意:**若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。
示例 1:
输入: s = "anagram", t = "nagaram"
输出: true
示例 2:
输入: s = "rat", t = "car"
输出: false
提示:
1 <= s.length, t.length <= 5 * 10^4s和t仅包含小写字母
进阶: 如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?
解题思路
判断两个字符串是否为字母异位词,核心是要检查两个字符串中每个字符出现的次数是否完全相同。
方法一:排序法 将两个字符串排序后比较是否相等。如果是字母异位词,排序后的结果必然相同。时间复杂度为 O(n log n)。
方法二:哈希表计数法(推荐) 使用哈希表记录每个字符出现的次数。遍历第一个字符串时增加计数,遍历第二个字符串时减少计数。最后检查所有计数是否都为0。
方法三:数组计数法 由于题目限定只有小写字母,可以用长度为26的数组代替哈希表,进一步优化空间使用。
优化思路: 首先检查两字符串长度是否相等,不等则直接返回false。对于小写字母场景,数组计数法是最优解,既节省空间又提高访问效率。
代码实现
class Solution {
public:
bool isAnagram(string s, string t) {
if (s.length() != t.length()) {
return false;
}
vector<int> count(26, 0);
for (int i = 0; i < s.length(); i++) {
count[s[i] - 'a']++;
count[t[i] - 'a']--;
}
for (int i = 0; i < 26; i++) {
if (count[i] != 0) {
return false;
}
}
return true;
}
};
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
if len(s) != len(t):
return False
count = [0] * 26
for i in range(len(s)):
count[ord(s[i]) - ord('a')] += 1
count[ord(t[i]) - ord('a')] -= 1
return all(c == 0 for c in count)
public class Solution {
public bool IsAnagram(string s, string t) {
if (s.Length != t.Length) {
return false;
}
int[] count = new int[26];
for (int i = 0; i < s.Length; i++) {
count[s[i] - 'a']++;
count[t[i] - 'a']--;
}
for (int i = 0; i < 26; i++) {
if (count[i] != 0) {
return false;
}
}
return true;
}
}
/**
* @param {string} s
* @param {string} t
* @return {boolean}
*/
var isAnagram = function(s, t) {
if (s.length !== t.length) return false;
const count = {};
for (let char of s) {
count[char] = (count[char] || 0) + 1;
}
for (let char of t) {
if (!count[char]) return false;
count[char]--;
}
return true;
};
复杂度分析
| 解法 | 时间复杂度 | 空间复杂度 |
|---|---|---|
| 数组计数法 | O(n) | O(1) |
| 哈希表法 | O(n) | O(1) |
| 排序法 | O(n log n) | O(1) |
其中 n 为字符串长度。数组计数法是最优解法,时间复杂度为线性,空间复杂度为常数(固定26个字母)。
相关题目
. Group Anagrams (Medium)
. Palindrome Permutation (Easy)
. Find All Anagrams in a String (Medium)