算法练习-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了,望博友们给个支持!!!

相关推荐
greenbbLV几秒前
中小公司积分商城选型:SaaS与私有化方案对比解析
大数据·前端·小程序
DuHz25 分钟前
论文解读:用于数据分析的极值点对称模态分解方法 (Extreme-point Symmetric Mode Decomposition,ESMD)
论文阅读·算法·信息与通信·信号处理
看昭奚恤哭31 分钟前
Flutter 布局核心思想
开发语言·javascript·flutter
HZZD_HZZD44 分钟前
用电负荷聚类分析实战:基于`scikit-learn`的`K-Means`与`DBSCAN`双算法对比、`PCA`降维可视化与智能电表负荷画像全流程
算法·scikit-learn·kmeans
MIngYaaa5201 小时前
2026暑期牛客多校1 2026-7-17
数据结构·算法
wabs6661 小时前
关于图论【卡码网107.寻找存在的路线的思考】
数据结构·算法·图论
朝阳5811 小时前
Cesium `Camera.flyTo`:“飞过去“
javascript
半兽先生1 小时前
大模型技术开发与应用——4.大模型提示词工程实战
人工智能·算法
NutShell Wang1 小时前
Vite 8.1 深度拆解:Rolldown 统一打包器如何终结前端构建的「双引擎时代」
前端·rust·开源·vite·开发者工具·vibe coding
朱容zr3331331 小时前
请解释“回表”的概念。
java·前端·数据库