我当时在查询有关codility的问题,遇到this problem时我写了这样的内容:
function impact(s) {
let imp = 4; // max possible impact
for (let i = 0; i < s.length; i++) {
if (s[i] === 'A') return 1;
else if (s[i] === 'C') imp = Math.min(imp, 2);
else if (s[i] === 'G') imp = Math.min(imp, 3);
else if (s[i] === 'T') imp = Math.min(imp, 4);
}
return imp;
}
function solution(S, P, Q) {
const A = new Array(P.length);
for (let i = 0; i < P.length; i++) {
const s = S.slice(P[i], Q[i] + 1);
A[i] = impact(s);
}
return A;
}
还有it failed all the performance tests
现在,我将其更改为以下代码,我认为它会变慢,但令我惊讶的是it scored 100%:
function solution(S, P, Q) {
let A = []
for (let i = 0; i < P.length; i++) {
let s = S.slice(P[i], Q[i] + 1)
if (s.indexOf('A') > -1) A.push(1)
else if (s.indexOf('C') > -1) A.push(2)
else if (s.indexOf('G') > -1) A.push(3)
else if (s.indexOf('T') > -1) A.push(4)
}
return A
}
这对我没有意义,因为我使用的是4 indexOf
,它应该比同一字符串的1个线性迭代慢。但这不是。
那么,String。indexOf()
是如何工作的,为什么4 .indexOf
比1次迭代快得多?
答案 0 :(得分:1)
在第一个解决方案中,您有两个循环。第二个循环在impact
中。第二个循环大致对应于第二个解决方案中的四个indexOf
。
第二个循环的一次迭代最多可以进行4次比较,最多可以进行 n 次迭代。因此,最多只能进行4n次比较。 indexOf
解决方案也可以这样说。这四个indexOf
中的每一个都可能需要扫描整个数组,这代表了 n 个比较。因此,这也是 4n 比较的最坏情况。
但是,主要区别在于,indexOf
执行的扫描不是在JavaScript中实现的,而是在高效的预编译代码中实现的,而第一种解决方案是使用(慢速)JavaScript代码来进行此扫描的。根据经验,使用本地String / Array方法(例如indexOf
,slice
,includes
等)总是比通过以下方式实现类似功能更有效:一个明确的for
循环。
要考虑的另一件事是,如果在位置 i 的数据中有一个“ A”,则第二个解决方案将在 i 比较后找到它(内部indexOf
实现),而第一个解决方案将在 4i 比较之后找到它,因为它还在相同的迭代过程中对其他三个字母进行比较它寻找一个“ A”。当没有“ A”但某处有“ C”时,……等额外成本降低。