我有一个noob javascript问题。假设我们有两个非常大的字符串(〜百万字符或更多)是相同的 - 它们具有相同的长度和相同的内容。 假设我们有这两个函数都做同样的事情(比较字符串):
function equals1(a, b) {
return a === b;
}
function equals2(a, b) {
if (a.length !== b.length) {
return false;
}
for (var i = 0; i < a.length; ++i) {
if (a[i] !== b[i]) {
return false;
}
}
return true;
}
为什么第一个函数(equals1())几乎是第二个函数的两倍? 如何改进第二个以使其表现与第一个一样好?
答案 0 :(得分:2)
第一个函数更快,因为它不必检查i < a.length
一百万次,并且在i
上执行一百万次递增操作。
答案 1 :(得分:1)
根据ECMAScript委员会中的人员,很可能Javascript正在进行字符串实习(Do common JavaScript implementations use string interning?)。我认为那时===将是O(1)但是基于原始海报的性能测试,它是O(n),因为双倍的字符串使得相等的时间加倍。不用字符串实习真的很难过它们应该如此。
更新:JSPerf
原始海报声明应该支持O(N)复杂性 来自http://jsperf.com/eqaulity-is-constant-time 似乎即使我有16倍大的字符串,时间也不会超过1-2%
因此,请重新考虑我所抨击的事情和你的选票
换句话说:
当你做
时var str1 = "stringwithmillionchars"; //stored in address 51242
var str2 = "stringwithmillionchars"; //stored in address 12313
“stringwithmillionchars”将在内存地址201012中存储一次 并且str1和str2都将“指向此地址201012.此地址可以通过某种散列来确定,以映射到内存中的特定位置。
所以在做的时候
"stringwithmillionchars"==="stringwithmillionchars"
看起来像
getContentOfAddress(51242)===getContentOfAddress(12313)
或201012 === 201012
需要O(1)/恒定时间
示例中的for循环(equals2())具有O(N)时间,其中N是两个字符串的长度。那是因为它必须在每对字符之间进行N次比较,并在i和str.length之间进行N次比较。
注意:为了说明目的,随机选择了地址编号..
重要:根据我的问题(Why Javascript ===/== string equality sometimes has constant time complexity and some times has linear time complexity)的性能比较,只有在直接使用引号分配字符串时才会进行实习,否则比较将采用线性时间而不是常数,因为char- to-char比较发生。
答案 2 :(得分:0)
第一个做同样的事情。如果字符串长度不同,则返回false。然后它检查相同索引处的字符是否相同。但是,它是在JS实现级别实现的,因此它的运行速度与C,C ++,Java或编写JavaScript实现的任何语言一样快。
答案 3 :(得分:0)
您可以执行以下操作来使您的equals2
功能快两倍:
function equals2(a, b) {
if (a.length !== b.length) {
return false;
}
for (var i = 0; i < a.length/2; ++i) {
if (a[i] !== b[i] || a[a.length-i-1] !== b[b.length-i-1]) {
return false;
}
}
return true;
}