当前位置: 首页 > news >正文

49-有效的字母异位词

给定两个字符串 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 字符怎么办?你能否调整你的解法来应对这种情况?

方法一:排序比较法

将字符串转换为字符数组,排序后比较是否相同。

function isAnagram(s: string, t: string): boolean {if (s.length !== t.length) return false;// 将字符串转换为字符数组并排序const sSorted = s.split('').sort().join('');const tSorted = t.split('').sort().join('');return sSorted === tSorted;
}

方法二:哈希表统计法

使用哈希表统计每个字符的出现次数,比较两个哈希表是否相同。

function isAnagram(s: string, t: string): boolean {if (s.length !== t.length) return false;const mapS = new Map<string, number>();const mapT = new Map<string, number>();// 统计s中字符频率for (const char of s) {mapS.set(char, (mapS.get(char) || 0) + 1);}// 统计t中字符频率for (const char of t) {mapT.set(char, (mapT.get(char) || 0) + 1);}// 比较两个哈希表是否相同if (mapS.size !== mapT.size) return false;for (const [char, count] of mapS.entries()) {if (mapT.get(char)! !== count) {return false;}}return true;
}
方法三:数组计数法(针对小写字母优化)

使用固定大小的数组(26 个元素)统计每个字符的出现次数。

function isAnagram(s: string, t: string): boolean {if (s.length !== t.length) return false;const count = new Array(26).fill(0);// 统计s中字符频率(增加计数)for (const char of s) {count[char.charCodeAt(0) - 'a'.charCodeAt(0)]++;}// 统计t中字符频率(减少计数)for (const char of t) {const index = char.charCodeAt(0) - 'a'.charCodeAt(0);count[index]--;// 如果某个字符计数小于0,说明t中该字符多于sif (count[index] < 0) {return false;}}return true;
}
方法四:Unicode 支持版本

使用哈希表统计字符频率,支持处理任意 Unicode 字符。

function isAnagram(s: string, t: string): boolean {if (s.length !== t.length) return false;const map = new Map<string, number>();// 统计s中所有Unicode字符的频率for (let i = 0; i < s.length; i++) {const char = s[i];// 处理代理对(surrogate pair)if (i < s.length - 1 && isSurrogatePair(s, i)) {const codePoint = getCodePoint(s, i);const str = String.fromCodePoint(codePoint);map.set(str, (map.get(str) || 0) + 1);i++; // 跳过代理对的第二个字符} else {map.set(char, (map.get(char) || 0) + 1);}}// 检查t中所有Unicode字符的频率for (let i = 0; i < t.length; i++) {const char = t[i];if (i < t.length - 1 && isSurrogatePair(t, i)) {const codePoint = getCodePoint(t, i);const str = String.fromCodePoint(codePoint);const count = map.get(str) || 0;if (count === 0) return false;map.set(str, count - 1);i++;} else {const count = map.get(char) || 0;if (count === 0) return false;map.set(char, count - 1);}}// 确保所有字符的计数都为0for (const count of map.values()) {if (count !== 0) return false;}return true;
}// 判断两个字符是否构成代理对
function isSurrogatePair(str: string, index: number): boolean {const code = str.charCodeAt(index);return code >= 0xD800 && code <= 0xDBFF && index + 1 < str.length && str.charCodeAt(index + 1) >= 0xDC00 && str.charCodeAt(index + 1) <= 0xDFFF;
}// 获取代理对的码点值
function getCodePoint(str: string, index: number): number {const high = str.charCodeAt(index);const low = str.charCodeAt(index + 1);return ((high - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000;
}

复杂度分析

方法时间复杂度空间复杂度适用范围
方法一(排序)O(n log n)O(n)所有字符类型,依赖排序算法
方法二(哈希表)O(n)O(k)所有字符类型,k 为不同字符的数量
方法三(数组)O(n)O(1)仅适用于小写字母
方法四(Unicode)O(n)O(k)所有 Unicode 字符,处理代理对

测试示例

// 示例1测试
console.log(isAnagram("anagram", "nagaram"));  // 输出: true// 示例2测试
console.log(isAnagram("rat", "car"));          // 输出: false// 测试大小写敏感
console.log(isAnagram("a", "A"));              // 输出: false// 测试Unicode字符
console.log(isAnagram("😀😁😂", "😂😁😀"));    // 输出: true
console.log(isAnagram("你好", "好你"));        // 输出: true

方法选择建议

  • 方法一简单直观,但时间复杂度较高,适用于小规模数据或快速验证。
  • 方法二通用且高效,适用于各种字符集,但需要额外的哈希表空间。
  • 方法三针对小写字母优化,空间效率最高,是处理纯小写字母输入的首选。
  • 方法四专门处理 Unicode 字符,包括代理对,适用于国际化场景。

在实际应用中,如果输入仅限于小写字母,推荐使用方法三;如果需要处理任意 Unicode 字符,方法四是最佳选择。

http://www.lqws.cn/news/527257.html

相关文章:

  • 设计模式精讲 Day 14:命令模式(Command Pattern)
  • Web基础关键_001_HTML(一)
  • docker环境下java参数传递与获取
  • FANUC机器人教程:用户坐标系标定及其使用方法
  • 学习永无止境
  • 程序的更新总结
  • 简易服务器(TCP)
  • 川翔云电脑全新上线:三维行业高效云端算力新选择
  • Kotlin环境搭建与基础语法入门
  • 鸿蒙边缘智能计算架构实战:多线程图像采集与高可靠缓冲设计
  • MIT 6.S081—环境配置和初步学习day01(VMware和Ubuntu安装)
  • Go 语言中的接口
  • 黑马ReactDay02
  • 《告别一换就崩:前端游戏物理引擎适配层设计哲学》
  • Vue样式绑定与条件渲染详
  • C++新纪元:深入C++11/14/17/20核心特性与名企面试精粹(完整版)--8000字硬核解析 | 腾讯/阿里/字节真题实战
  • 数据分享:交通数据-地铁乘坐站记录数据
  • 随记:WebMvcConfigurationSupport 和WebMvcConfigurer 的区别
  • 第4篇:响应处理——返回数据给客户端(Gin文件下载,JSON,XML等返回)
  • Vue-14-前端框架Vue之应用基础嵌套路由和路由传参
  • 51c~嵌入式~PLC~三菱~合集1
  • spring-ai 1.0.0 (1)模型调用能力
  • 高中成绩可视化平台开发笔记
  • 六个安全Agent设计模式:有效防止Prompt注入攻击
  • 城市综合管廊监测,智能化安全监测,多源感知,三维可视化监控
  • c++面向对象编程
  • 微积分 - 无穷小量
  • 数据分享:环境科学与公共健康行业-空气质量数据集
  • 汽车一键启动升级手机控车
  • SQL(6)