力扣刷题#5:LeetCode242字母异位词_从 7ms 到 0ms 就差一个数组

力扣刷题#5:有效的字母异位词_从 7ms 到 0ms 就差一个数组

哈希表好用,但不是万能的。有时候,一个 26 长度的数组比什么 STL 都管用。


题目

给定两个字符串 s 和 t,判断它们是否是字母异位词(每个字母出现次数相同)。

输入: s = "anagram", t = "nagaram"  → true
输入: s = "rat", t = "car"         → false

第一版:杀鸡用牛刀

我的思路很清晰:遍历 s 记次数,遍历 t 减次数,减到负数就返回 false。

unordered_map<char, int> smap;
for (int i = 0; i < slen; i++) smap[s[i]]++;
for (int i = 0; i < tlen; i++) {
    smap[t[i]]--;
    if (smap[t[i]] < 0) return false;
}

逻辑没问题,通过了。但耗时 7ms

看了一下题解区,有人 0ms。凭什么?同样的逻辑,差距这么大?


提示:只用小写字母

"题目说了只包含小写字母,你开个 26 的数组就行了。"

就这一句话,我就知道差距在哪了。

unordered_map<char, int>   → 哈希计算 + 动态分配 + 内存开销
int count[26]              → 栈上固定空间,取址就完事

一个是要算哈希、要扩容、要处理冲突;另一个就是 base_address + index * 4 一条指令。


第二版:数组版

int smap[200] = {0};
for (int i = 0; i < slen; i++) smap[0 + int(s[i])]++;
for (int i = 0; i < tlen; i++) {
    smap[0 + int(t[i])]--;
    if (smap[0 + int(t[i])] < 0) return false;
}

改成数组后,时间直接掉到接近 0ms。虽然用了 200 而不是 26,但数组访问就是数组访问,比哈希表快太多了。


最终版:细节拉满

class Solution {
public:
    bool isAnagram(string s, string t) {
        if (s.length() != t.length()) return false;

        int count[26] = {0};
        for (char c : s) count[c - 'a']++;
        for (char c : t) {
            count[c - 'a']--;
            if (count[c - 'a'] < 0) return false;
        }
        return true;
    }
};
改动 说明
count[26] 而非 count[200] 小写字母就 26 个,精确分配
c - 'a' 而非 int(s[i]) 'a'→0,'b'→1……语义自解释
for (char c : s) 范围 for 更简洁,不用管下标

学到了什么

数据结构的选择比代码逻辑更重要。

同样的算法(遍历 → 记数 → 减数 → 判断),用哈希表 7ms,用数组 ≈0ms。不是哈希表不好,而是当数据范围已知且很小时,数组永远是最高效的选择

场景 用什么 原因
字母异位词(26 种) int[26] 范围固定,直接寻址
存在重复元素(值域未知) unordered_set 范围未知,哈希表灵活
两数之和(需要配对) unordered_map 需要存键值对
大数据量模糊查找 哈希表 伸缩性好

栈上开数组 ≈ 一条指令,哈希表 ≈ 几十条指令。 当你知道数据范围不超过 26,就别用哈希表。


写于 2026-06-04。熟悉了哈希表后,要知道什么时候不用它——这才叫真正学会了。

posted @ 2026-06-04 23:00  STA_running  阅读(6)  评论(0)    收藏  举报