算法 | 有效的字母异位词(哈希表的应用)

105 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 14 天,点击查看活动详情

题目描述:

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

注意: 若 s 和 t **中每个字符出现的次数都相同,则称 s 和 t **互为字母异位词。

在前文中提及了哈希表相关的概念,正是这道算法题的一种比较好的解法。

在前端中,数组可以理解成是一个哈希结构,Object、Set、WeakSet、Map、WeakMap 等也都属于是哈希结构,使用哈希表来进行查找速度更快。

实现方案

第一种 暴力法

提到暴力法不得不说的就是它的时间复杂度了,双层 for 循环进行遍历,同时记录字符重复出现的次数。

时间复杂度为 O(n^2)。

第二种 哈希表

这道题目主要来说一说哈希表的实现思路:

  • 首先判断两个字符串的长度是否相同,如果不相同就一定不是异位词,返回 false
  • 定义一个数组,默认值为 0
  • 以字符 'a' 的 Unicode 编码作为一个基准,用当前字符的值减去 'a' 的 Unicode 编码,得到的差值作为数组的下标,这样从 a-z 的26个英文字母的下标就是 0-25
  • 遍历第一个字符串,第一个串中字符的计数每次 +1
  • 遍历第二个字符串,如果在这个循环中当前字符的计数为 0,说明不是异位词(因为减 1 之后会变成 -1),第二个串中字符的计数每次 -1
  • 循环完毕,最后返回 true

时间复杂度:O(n),代码如下:

var isAnagram = function(s, t) {
    if(s.length !== t.length) return false;
    const arr = new Array(30).fill(0);
    const base = 'a'.charCodeAt();
    for(const i of s) {
        arr[i.charCodeAt() - base]++;
    }
    for(const i of t) {
        if(!arr[i.charCodeAt() - base]) return false;
        arr[i.charCodeAt() - base]--;
    }
    return true;
};

第三种 排序法

排序法相对来说比较巧妙,代码量比较少,但是时间复杂度上还是哈希表更低一些。

思路就是就是将两个字符串中的元素按照字母顺序排列,再进行对比,如果有不同的字母,则不是异位词。

时间复杂度:O(nlogn)。

var isAnagram = function(s, t) { 
    return s.length == t.length && [...s].sort().join('') === [...t].sort().join('') 
}

用到的相关方法

  • charCodeAt

charCodeAt() 方法可返回指定位置的字符的 Unicode 编码,返回值是 0 - 65535 之间的整数,表示给定索引处的 UTF-16 代码单元

var str = "apple";  
var n = str.charCodeAt(0);
console.log(n)

等同于:

'a'.charCodeAt()

运行结果: 97