字符串的indexOf方法在JavaScript中如何工作

时间:2019-07-28 12:42:15

标签: javascript algorithm indexof

我当时在查询有关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次迭代快得多?

1 个答案:

答案 0 :(得分:1)

在第一个解决方案中,您有两个循环。第二个循环在impact中。第二个循环大致对应于第二个解决方案中的四个indexOf

第二个循环的一次迭代最多可以进行4次比较,最多可以进行 n 次迭代。因此,最多只能进行4n次比较。 indexOf解决方案也可以这样说。这四个indexOf中的每一个都可能需要扫描整个数组,这代表了 n 个比较。因此,这也是 4n 比较的最坏情况。

但是,主要区别在于,indexOf执行的扫描不是在JavaScript中实现的,而是在高效的预编译代码中实现的,而第一种解决方案是使用(慢速)JavaScript代码来进行此扫描的。根据经验,使用本地String / Array方法(例如indexOfsliceincludes等)总是比通过以下方式实现类似功能更有效:一个明确的for循环。

要考虑的另一件事是,如果在位置 i 的数据中有一个“ A”,则第二个解决方案将在 i 比较后找到它(内部indexOf实现),而第一个解决方案将在 4i 比较之后找到它,因为它在相同的迭代过程中对其他三个字母进行比较它寻找一个“ A”。当没有“ A”但某处有“ C”时,……等额外成本降低。