You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何优化通过交换实现连续整数升序排列的JavaScript函数效率?

问题根源分析

你当前的代码看起来只有一层循环,但arr.indexOf(i+1)方法底层会遍历整个数组查找目标值,单次操作时间复杂度为O(n),因此整体时间复杂度是O(n²)。当输入规模达到100000时,运算量会达到10^10次,远超JS在10秒内可处理的运算上限,因此会触发超时。

优化方案1:基于原逻辑新增索引映射(时间复杂度O(n),空间复杂度O(n))

我们可以提前构建一个「值→索引」的映射表,后续查找目标值位置直接从表中取值,不需要每次遍历数组,交换元素时同步更新映射表保证数据准确即可,优化后代码如下:

function minimumSwaps(arr) {
    let swaps = 0;
    const len = arr.length;
    // 因为元素是1~n的连续整数,用数组当哈希表效率更高
    const valueToIndex = new Array(len + 1);
    for (let i = 0; i < len; i++) {
        valueToIndex[arr[i]] = i;
    }

    for (let i = 0; i < len; i++) {
        const target = i + 1;
        if (arr[i] !== target) {
            // O(1)开销获取目标值索引
            const targetIndex = valueToIndex[target];
            const currentVal = arr[i];
            // 交换元素
            arr[i] = target;
            arr[targetIndex] = currentVal;
            // 更新被交换元素的索引映射
            valueToIndex[currentVal] = targetIndex;
            swaps++;
        }
    }
    return swaps;
}

优化方案2:循环节计数法(时间复杂度O(n),空间复杂度O(n))

这是求排列最小交换次数的经典算法:将数组视为一个排列,每个元素指向它应该放置的位置,会形成若干闭合循环。长度为k的循环仅需要k-1次交换即可让所有元素归位,累加所有循环的k-1值就是最终最小交换次数,代码如下:

function minimumSwaps(arr) {
    let swaps = 0;
    const len = arr.length;
    const visited = new Array(len).fill(false);

    for (let i = 0; i < len; i++) {
        // 已访问过或元素已在正确位置则跳过
        if (visited[i] || arr[i] === i + 1) continue;
        let cycleLength = 0;
        let current = i;
        // 遍历当前循环节
        while (!visited[current]) {
            visited[current] = true;
            // 跳转到当前元素应该所在的位置
            current = arr[current] - 1;
            cycleLength++;
        }
        swaps += cycleLength - 1;
    }
    return swaps;
}

以上两种方案处理100000规模的输入都可以在毫秒级完成,不会触发超时限制。

内容的提问来源于stack exchange,提问作者Lisa Modenbach

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 16:48:02