[LeetCode] 242.有效的字母异位词

img

1. 问题描述

242. 有效的字母异位词

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的 字母异位词。

示例 1:

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

示例 2:

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

提示:

  • 1 <= s.length, t.length <= 5 * 104
  • s 和 t 仅包含小写字母

进阶: 如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?


2. 实现思路

2.1 自己的思路

~~(一定要写出来啊喂)~

因为刚学哈希表,一开始自动尝试着先以C#的HashSet看能不能实现,但是测试用例通过为47/55,遇到”aaca”和”ccac”时报错

为什么呢?因为HashSet只能存字母是否出现过,但无法确定字母的个数,那么就只好改成Dictionary了

接下来的惯性思维是创建两个dict,一个字符串存一个,然后对比就出来了

但发现还可以优化,实际上只用一个Dictionary<char, int>就行了,键值对代表字母以及出现的次数,先遍历s对其出现次数++,然后遍历t对其出现次数—,那么如果字典值中有负数,则不是字母异位词

/*
 * @lc app=leetcode.cn id=242 lang=csharp
 *
 * [242] 有效的字母异位词
 */

// @lc code=start
public class Solution
{
    public bool IsAnagram(string s, string t)
    {
        if (s.Length != t.Length) return false;

        Dictionary<char, int> sCount = new();
        foreach (char c in s)
            sCount[c] = sCount.GetValueOrDefault(c) + 1;

        foreach (char c in t)
            sCount[c] = sCount.GetValueOrDefault(c) - 1;

        foreach (var i in sCount.Values)
            if (i < 0) return false;

        return true;
    }
}
// @lc code=end

时间复杂度:O(n)

空间复杂度:O(n)

2.2 题解思路

242.有效的字母异位词 | 哈希表 | 数组 | 字符统计

相比我上面的解法,随想录里给出的还可以对空间进一步优化

因为题目中的字符串保证全小写字母,那么我们用size为26的数组,里面的数字就是字母出现次数,索引对应字母ASCII即可

class Solution {
public:
    bool isAnagram(string s, string t) {
        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;
    }
};
 public bool IsAnagram(string s, string t) {
         int sl=s.Length,tl=t.Length;
        if(sl!=tl) return false;
        int[] a = new int[26];
        for(int i = 0; i < sl; i++){
             a[s[i] - 'a']++;
             a[t[i] - 'a']--;
        }       
        foreach (int i in a)
        {
            if (i != 0)
                return false;
        }
        return true;
    }
  • 时间复杂度: O(n)
  • 空间复杂度: O(1)

2.3 优化(或者敲一遍题解?)

根据自己的理解敲一遍如下:

/*
 * @lc app=leetcode.cn id=242 lang=csharp
 *
 * [242] 有效的字母异位词
 */

// @lc code=start
public class Solution
{
    public bool IsAnagram(string s, string t)
    {
        if (s.Length != t.Length) return false;

        int[] a = new int[26];
        for (int i = 0; i < s.Length; i++)
        {
            a[s[i] - 'a']++;
            a[t[i] - 'a']--;
        }
        for (int i = 0; i < 26; i++)
            if (a[i] != 0) return false;

        return true;
    }
}
// @lc code=end

可以清晰感受到,第一个优化点是使用数组代替字典,第二个优化点是把s和t两个for合并成一个(虽然对时间复杂度没影响hhh)

另外比较小的点是,末尾处a[i] ≠ 0的写法,相比原先<0的写法,此处可读性更好,因为≠0能更清楚表达计数不为0即不为字母异位词的含义


3. 补充知识と杂谈,总结

  • 活用char对应ASCII与数组的联系
  • 另外就是吐槽vscode的leetcode插件关于手动指定本地txt测试用例文件中,格式怎么写的问题

官方插件地址:Github地址

相关issue:issue#794
issue#739

貌似除了第一题两数之和给的示例

[1,2,3]\n3

就没有详细描述惹

根据示例可以猜想,应该是一行对应一个测试用例,用\n分隔参数,但是对于此题字符串输入需要额外处理,调试了半天发现以下方法可以

""anagram"\n"nagaram"
"car"\n"rat"
"aacc"\n"ccac""

怎么写的呢,首先按照原思路,\n分隔参数,就是这样:

"anagram"\n"nagaram"
"car"\n"rat"
"aacc"\n"ccac"

接下来再给首行开头,以及末行结尾加上引号即可

posted @ 2026-08-08 10:53  绘星tsuki  阅读(4)  评论(0)    收藏  举报