日期:2023.8.28(回家摸了一个多星期了aaa)
参考:代码随想录、力扣
难度:简单
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。
示例 1:
输入: s = "anagram", t = "nagaram"
输出: true
示例 2:
输入: s = "rat", t = "car"
输出: false
提示:
进阶: 如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?
class Solution {
#define SOLUTION 3
public:
bool isAnagram(string s, string t) {
#if SOLUTION == 1 // 两个哈希表+遍历比较
// 时间复杂度:O(n+m+n), 空间复杂度:O(1+1)=O(1),因为size不超过26
// s 哈希表
unordered_map<char, int> s_cnt, t_cnt;
for (const auto& ch :s) {
s_cnt[ch]++;
}
// t 哈希表
for (const auto& ch: t) {
t_cnt[ch]++;
}
// 比较
if (s_cnt.size() != t_cnt.size()) {
return false;
} else {
for (const auto& entry: s_cnt) {
if (entry.second != t_cnt[entry.first]) { // s_cnt中字符个数不等于t_cnt中对应字符个数
return false;
}
}
}
return true;
#elif SOLUTION == 2 // 一个记录哈希表(也可以用数组代替),好巧妙啊啊,完全想不到
// 时间复杂度:O(n+m+n),空间复杂度:O(1)
unordered_map<char, int> record;
// 先加一遍
for (const auto& ch: s) {
record[ch]++;
}
// 再减一遍
for (const auto& ch: t) {
record[ch]--;
}
// 判断是否为0
for (const auto& entry: record) {
if (entry.second != 0) {
return false;
}
}
return true;
#elif SOLUTION == 3 // 代码随想录ver(直接用辅助数组)
int record[26] = {0};
for (int i = 0; i < s.size(); i++) {
// 并不需要记住字符a的ASCII,只要求出一个相对数值就可以了
record[s[i] - 'a']++;
}
for (int i = 0; i < t.size(); i++) {
record[t[i] - 'a']--;
}
for (int i = 0; i < 26; i++) {
if (record[i] != 0) {
// record数组如果有的元素不为零0,说明字符串s和t 一定是谁多了字符或者谁少了字符。
return false;
}
}
// record数组所有元素都为零0,说明字符串s和t是字母异位词
return true;
#endif
}
};
两个哈希表+比较是否相等
时间复杂度:O(n+m+n),
空间复杂度:O(1+1)=O(1),因为size不超过26
一个哈希表+判断是否为0
时间复杂度:O(n+m+n)
空间复杂度:O(1)
一个辅助数组+判断是否为0(本质同2)
时间复杂度:O(n+m+n)
空间复杂度:O(1)
- 养成这样的习惯:遇到一道题目,感觉想要使用哈希法的时候,先看看能不能用数组。如果哈希值比较大,用数组就不太合适了。但能用数组尽量用数组,会比较快(set和map需要一些映射,且结构复杂,会浪费时间)。
- 哈希法应用场景:
- 当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法
- 如果在做面试题目的时候遇到需要判断一个元素是否出现过的场景也应该第一时间想到哈希法