leetcode 有效的字母异位词

118 阅读2分钟

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

示例 1:

输入: s = "anagram", t = "nagaram"
输出: true

示例 2:

输入: s = "rat", t = "car"
输出: false

说明: 你可以假设字符串只包含小写字母。

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

我的算法实现:

/**
 * @param {string} s
 * @param {string} t
 * @return {boolean}
 */
var isAnagram = function (s, t) {
  const sLen = s.length;
  const tLen = t.length;
  // 如果长度不同,肯定不是
  if (sLen !== tLen) {
    return false;
  }
  const sObj = {}, tObj = {}
  // 将字符串转换成对象,由于有可能存在相同的字符,所以同时需要记下字母出现的个数
  for (let i = 0; i < sLen; i ++) {
    sObj[s.charAt(i)] = (sObj[s.charAt(i)] || 0) + 1;
    tObj[t.charAt(i)] = (tObj[t.charAt(i)] || 0) + 1;
  }
  const sKeys = Object.keys(sObj)
  // 然后逐一比较即可,不相等就代表不是
  for (let k = 0; k < sKeys.length; k ++) {
    if (sObj[sKeys[k]] !== tObj[sKeys[k]]) {
      return false;
    }
  }
  return true;
};

第一次理解错了,异位看成是移位了,导致第一次提交错误。

我的思路很简单,就是将 s 和 t 字母以及出现的个数保存为对象,然后循环对象看看彼此相不相等。

我还想到了一种方法,就是如果 s 中的字母在 t 中有,那么就删除 t 中对应的字母,直到 s 的字母全部遍历完成,如果都是相等的,那么说明是,否则就不是。这个最后得出的结果的时间很大:

/**
 * @param {string} s
 * @param {string} t
 * @return {boolean}
 */
var isAnagram = function (s, t) {
  if (s.length !== t.length) {
    return false;
  }
  const tArr = t.split('');
  for (let i = 0; i < s.length; i ++) {
    let index = tArr.indexOf(s.charAt(i))
    if (index === -1) {
      return false;
    }
    tArr.splice(index, 1);
  }
  return true;
};

光看代码比上面的要少,只不过使用了三个内部方法,可能花费时间最多的也是这个原因。

官方的讲解: 有效的字母异位词

这次官方的讲解没有吸引人的,第一种通过排序的方法还可以,只不过时间复杂度同样很大;第二个方法是利用哈希表,跟我上面那个有异曲同工之处,只不过在空间上,明显官方的更好,毕竟一直都是在一个对象上操作。

在 js 中由于可以动态添加属性,所以不用像官方那样刚开始就是 26 的英文字母,直接采用 s 在对应字母上 +1 (不管有没有,没有给个默认值 0), t 则是在对应字母上 -1 。完成后只要发现有不为 0 的,那么就返回 false。


来源:力扣(LeetCode)