算法练习-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和出现的次数的映射
  • 我本来担心map[char]--;会不会为负数,我的担心是多余的,在他为负数之前,if (!map[char])就已经返回了
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了,望博友们给个支持!!!

相关推荐
2301_7816686117 分钟前
前端基础 JS Vue3 Ajax
前端
上单带刀不带妹40 分钟前
前端安全问题怎么解决
前端·安全
Fly-ping43 分钟前
【前端】JavaScript 的事件循环 (Event Loop)
开发语言·前端·javascript
SunTecTec1 小时前
IDEA 类上方注释 签名
服务器·前端·intellij-idea
啊我不会诶1 小时前
CF每日5题(1500-1600)
c++·学习·算法
巴伦是只猫1 小时前
Java 高频算法
java·开发语言·算法
点云SLAM2 小时前
C++中std::string和std::string_view使用详解和示例
开发语言·c++·算法·字符串·string·c++标准库算法·string_view
在逃的吗喽2 小时前
黑马头条项目详解
前端·javascript·ajax
袁煦丞2 小时前
有Nextcloud家庭共享不求人:cpolar内网穿透实验室第471个成功挑战
前端·程序员·远程工作
小磊哥er2 小时前
【前端工程化】前端项目开发过程中如何做好通知管理?
前端