算法练习-Day4-有效的字母异位词

题目:

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

示例 1:

ini 复制代码
输入: s = "anagram", t = "nagaram"
输出: true

示例 2:

ini 复制代码
输入: s = "rat", t = "car"
输出: false

提示:

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

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

解释:

  • 字母异位词(anagram)指的是两个字符串,长度相同,且每个字符出现的次数都一样,顺序可以不同。
  • car 和 car 两个字符串完全一样,当然每个字符出现的次数都一样,所以它们是字母异位词。

实现:

1. 这是我之前学python的时候做的

python 复制代码
class Solution(object):
    def isAnagram(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: bool
        """
        # 母异位词必须是两个长度相同的字符串
        if len(s) == len(t):
            for i in s:
                # 每个字符出现的次数都一样
                if i not in t or s.count(i) != t.count(i):
                    # 如果有t中的字符不存在s中的某一字符,或者数量不一样,就返回False
                    return False
            return True
        else:
            return False

2. 下面是我用JavaScript的实现

2.1 用ASII码实现

  • 之所以会想到使用ASII码来实现原因主要是提示里有一条:st 仅包含小写字母,这是我的逻辑,不一定正确,大家可以帮忙指出问题
  • 另外我想的是这两个字符串里面包含的字符是完全相同的(只是顺序不同罢了),所以只要这两个字符串所有的字符转成ASII码值,然后综合相等,就可以了
js 复制代码
/**
 * @param {string} s
 * @param {string} t
 * @return {boolean}
 */
var isAnagram = function(s, t) {
    // 母异位词必须是两个长度相同的字符串
    if (s.length !== t.length) return false
    let sum1 = 0;
    let sum2 = 0;
    for (const char of s) {
        sum1 += char.charCodeAt();
    }
    for (const char of t) {
        sum2 += char.charCodeAt();
    }
    return sum1 === sum2
}

结果:

  • 两个示例都通过了
  • 但是有了反例:s ="ggii",t ="eekk"
  • 40 / 53 个通过的测试用例

2.2 用和python实现相同的方法

  • js没有直接统计一个字符在字符串中出现的次数的方法,我还去特意查了一下可以用str.split(char).length + 1来统计
  • 这里我犯了一个错误:我用了for...in来遍历字符串s了,注意:for...in遍历字符串只会遍历字符串的索引
js 复制代码
/**
 * @param {string} s
 * @param {string} t
 * @return {boolean}
 */
var isAnagram = function(s, t) {
    if (s.length !== t.length) return false
    for (let char of s) {
        if (!t.includes(char) || s.split(char).length !== t.split(char).length) {
            return false
        }
    }
    return true
};

结果:

  • 两个示例都通过了
  • 但是当面对超长字符串时,超时了,直接给浏览器干崩溃了
  • 其实时间复杂度只是O(n^2)

2.3 Deepseek给2.2的优化版本

js 复制代码
var isAnagram = function(s, t) {
    if (s.length !== t.length) return false;
    
    const count = {};
    // 统计s的字符
    for (let char of s) {
        count[char] = (count[char] || 0) + 1;
    }
    // 验证t的字符
    for (let char of t) {
        if (!count[char]) return false;
        count[char]--;
    }
    return true;
};

结果

  • 通过率100%

复杂度对比

方法 时间复杂度 空间复杂度
原始实现 O(n²) O(n)(split创建临时数组)
优化实现 O(n) O(1)(因为字母表固定大小)

关键点:当处理字符串问题时,尽量避免在循环内使用includes()split()等O(n)操作。

2.4 结合排序实现

  • 这个我一开始就想到了,但是我觉的直接使用sort排序是不是就像我昨天使用indexOf一样,就是说,用方法的话,那还能叫算法吗
  • 但是,这是一种方法,leedCode通过率100%
js 复制代码
/**
* 时间复杂度O(n log n)
* split(): O(n)
* sort(): 通常O(n log n)(取决于JS引擎实现)
* join(): O(n)
**/
var isAnagram = function(s, t) {
    if (s.length !== t.length) return false;
    return s.split('').sort().join('') === t.split('').sort().join('');
};

// 下面是Deepseek给的优化版### (O(n)时间,O(1)空间)
var isAnagram = function(s, t) {
    if (s.length !== t.length) return false;
    
    const count = new Array(26).fill(0); // 因为题目说明只含小写字母
    
    for (let i = 0; i < s.length; i++) {
        count[s.charCodeAt(i) - 97]++; // 'a'.charCodeAt() = 97
        count[t.charCodeAt(i) - 97]--;
    }
    
    return count.every(v => v === 0);
};

2.5 Cursor推荐使用哈希表计数法

  • 这个我本来也不懂,但是仔细一看这个和2.3就是一种方法
  • 就是用一个对象记载字符char和出现的次数的映射
  • 我本来担心mapchar--;会不会为负数,我的担心是多余的,在他为负数之前,if (!mapchar)就已经返回了
js 复制代码
var isAnagram = function(s, t) {
    if (s.length !== t.length) return false;
    const map = {};
    for (const char of s) {
        map[char] = (map[char] || 0) + 1;
    }
    for (const char of t) {
        if (!map[char]) return false;
        map[char]--;
    }
    return true;
};

总结:

有志者,事竟成,破釜沉舟,百万秦关终属楚; 苦心人,天不负,卧薪尝胆,三千越甲可吞吴。


虽然很简单的一个小算法题,但我也呕心沥血了,写完已经凌晨00:40了,望博友们给个支持!!!

相关推荐
竹林81841 分钟前
用 wagmi v2 + viem 监听链上事件,我踩了三天坑终于搞懂了实时日志与历史补全
javascript
Momo__1 小时前
VueUse createReusableTemplate —— 单文件组件内的模板复用神器
前端·vue.js
只一1 小时前
😭从回调地狱到 async/await:一文打通 Ajax 与 JS 异步编程
javascript
程序员小富1 小时前
我开源了一个开发者专属的智能 JSON 工具,得到了媳妇高度认可
前端·vue.js·后端
小小小小宇1 小时前
程序员如何给 LLM 装工具以及看懂推理过程
前端
写代码的皮筏艇1 小时前
React中的forwardRef
前端·react.js·面试
复杂网络1 小时前
Stable Diffusion 视觉大模型微调技术深度调研
算法
复杂网络1 小时前
基于 Stable Diffusion 架构的视觉大模型代表性工作与原理深度解析
算法
槑有老呆1 小时前
花三个月工资请了个 AI 程序员,结果它连青岛啤酒股价都查不了
前端
MrZhao4001 小时前
Agent Loop 如何用 Hook 扩展:权限、日志与工具拦截
算法