Javascript-查找字谜的更好解决方案-时间复杂度O(n log n)

时间:2019-04-24 04:39:57

标签: javascript time-complexity anagram

免责声明

大家好,我了解很少有Javascript问题/答案可以弄清楚如何找到两个单词是否是字谜。

我不只是在寻找一个可以判断两个单词/字符串是否是字谜的函数。我正在寻找一种比下面提供的功能更快的功能。目前,我认为以下函数的时间复杂度为 O(n log n)

我想找出一个时间复杂度为 O(n)的函数,或者运行时间比所提供的函数快的函数。

代码

const isAnagram = (str1, str2) => {

  str1 = str1.toLowerCase();
  str2 = str2.toLowerCase();


  if (str1.length !== str2.length) {
     return false
  }

  let sortStr1 = str1.split('').sort().join('').trim();
  let sortStr2 = str2.split('').sort().join('').trim();

  return sortStr1 === sortStr2
 };

console.log(isAnagram('dog', 'goD')); //true

2 个答案:

答案 0 :(得分:5)

您可以尝试基于计数的算法。

const isAnagram = (str1, str2) => {

  str1 = str1.toLowerCase();
  str2 = str2.toLowerCase();
  //and remove any char you think not important (like space) here
  
  if (str1.length !== str2.length) return false
  
  let counting = {}
  for(let c of str1) 
     if(counting[c]) ++counting[c]
     else counting[c] = 1
  
  for(let c of str2)
     if(counting[c]) --counting[c]
     else return false
  
  return true
};

console.log(isAnagram('dog', 'goD')); //true
console.log(isAnagram('eleven plus two', 'twelve plus one')); //true
console.log(isAnagram('dog', 'hot')); //false
console.log(isAnagram('banana', 'nana')); //false

答案 1 :(得分:1)

这是来自An Algorithm for Finding Anagrams并基于fundamental theorem of arithmetic的另一种可能的想法,其中指出:

  

每个大于1的整数本身就是质数,或者可以表示为质数的乘积,此外,该表示是唯一的,直到(除)因子的阶数为止。

因此,如果我们将字母表中的每个字母分配给一个质数,然后计算这些数字的乘积,则该数字将是唯一的(因为算术的基本定理)。这意味着对于字母的多集合,该多集合中每个字母的素数乘积是唯一的。然后,如果两个单词或句子具有相同的编号,则这两个单词或句子就是彼此的字谜。

实施:

let letters = {"a":2, "b":3, "c":5, "d":7, "e":11, "f":13, "g":17, "h":19, "i":23, "j":29, "k":31, "l":37, "m":41, "n":43, "o":47, "p":53, "q":59, "r":61, "s":67, "t":71, "u":73, "v":79, "w":83, "x":89, "y":97, "z":101};

const isAnagram = (str1, str2) =>
{
    str1 = str1.toLowerCase();
    str2 = str2.toLowerCase();            
    let repStr1 = 1, repStr2 = 1;

    for (let i = 0; i < Math.max(str1.length, str2.length); i++)
    {
        repStr1 *= (str1[i] && letters[str1[i]]) ? letters[str1[i]] : 1;
        repStr2 *= (str2[i] && letters[str2[i]]) ? letters[str2[i]] : 1;
    }

    return (repStr1 === repStr2);
};

console.log("[dog, goD] Anagrams?", isAnagram('dog', 'goD'));
console.log("[dogo, goD] Anagrams?", isAnagram('dogo', 'goD')); 
console.log("[Roast Beef, Eat for BSE] Anagrams?", isAnagram('Roast Beef', 'Eat for BSE'));
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}

优势

  • 接受不同长度的字谜(请参见第三个示例)。
  • O(n)(仅需要一个循环)。

缺点

  • 不适用于大表达式,生成的数字将溢出。
  • 需要一个预定义的字母和引号之间的字典。
  • 除非包含字典,否则不适用于包含稀有字符的表达式,但是溢出会变得更加频繁。