Javascript - 查找字谜的更好解决方案 - 时间复杂度 O (n log n)
Posted
技术标签:
【中文标题】Javascript - 查找字谜的更好解决方案 - 时间复杂度 O (n log n)【英文标题】:Javascript - Better solution for finding anagrams - Time complexity O (n log n) 【发布时间】:2019-09-13 07:21:51 【问题描述】:免责声明
大家好,我知道很少有 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
【问题讨论】:
使用O(n)
排序,你的代码是O(n)
。顺便说一句,您尝试了什么:/
对不起,我不确定你的意思
像en.wikipedia.org/wiki/Counting_sort 这样的东西确实给你O(n)
排序复杂性。
所以你是说我的方法确实返回了 O(n) 的时间复杂度?
是的,如果你使用O(n)
排序方法。
【参考方案1】:
您可以尝试基于计数的算法。
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
【讨论】:
我相信这会给我们一个 O(n^2) 的时间复杂度? @mph85 为什么?你从哪里得到的? 不是我的错,我以为它是嵌套的,但它不是 if 语句中发生了什么?if(counting[c]) --counting[c]
这是什么意思?以及以下else counting[c] = 1
?
@mph85 第一个if(counting[c])
表示if(c in counting)
,第二个if(counting[c])
表示if(c in counting && c != 0)
【参考方案2】:
这是另一个可能的想法,来自: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)
(只需要一个循环)。
缺点
不适用于大型表达式,生成的数字会溢出。 需要一个预定义的字母和引物编号之间的字典。 不适用于包含稀有字符的表达式,除非您扩展字典,但溢出会变得更加频繁。【讨论】:
我认为这是回文,而不是字谜?以上是关于Javascript - 查找字谜的更好解决方案 - 时间复杂度 O (n log n)的主要内容,如果未能解决你的问题,请参考以下文章
javascript [438。查找字符串中的所有字谜] #tags:leetcode