【问题标题】:How to insert value in sorted array and keep array sorted? [duplicate]如何在排序数组中插入值并保持数组排序? [复制]
【发布时间】:2020-03-16 08:14:27
【问题描述】:

在数组中插入值并保持数组排序的最佳方法是什么?

例如这里是一个数组

const arr = [1, 4, 23, 45];

我可以使用 push 或 splice 方法添加一个新值,例如 16,我会得到修改后的数组:

[1, 4, 23, 45, 16]

但我需要保持数组排序:

[1, 4, 16, 23, 45]

保持数组排序的更好方法是什么?我应该在每次添加新值时排序,还是检测插入新值所需的索引?

【问题讨论】:

  • 识别要插入的位置将不那么复杂,而且很简单
  • 检测索引并放一个值是O(n),而排序通常是O(n*log(n))。因此在索引处插入更好。
  • 这真的取决于你数组的大小。如果是相对小的,那真的不会有什么不同。如果没有,请按照其他人的建议进行。代码的简单性/可读性通常比纯粹的性能更重要。

标签: javascript arrays


【解决方案1】:

只看复杂性:

  • 排序:最佳情况下为 O(nlogn)
  • 索引插入:最坏情况下的 O(n)
  • 智能排序:在最佳情况下为 O(n),使用诸如插入排序之类的算法,当数组几乎已经排序时效果很好
  • 二进制插入:O(logn) 这是首选方式

function  binaryInsertion(arr, element) {
    return binaryHelper(arr, element, 0, arr.length - 1);
}

function binaryHelper(arr, element, lBound, uBound) {
    if (uBound - lBound === 1) {
        // binary search ends, we need to insert the element around here       
        if (element < arr[lBound]) arr.splice(lBound, 0, element);
        else if (element > arr[uBound]) arr.splice(uBound+1, 0, element);
        else arr.splice(uBound, 0, element);
    } else {       
        // we look for the middle point
        const midPoint = Math.floor((uBound - lBound) / 2) + lBound;
        // depending on the value in the middle, we repeat the operation only on one slice of the array, halving it each time
        element < arr[midPoint]
            ? binaryHelper(arr, element, lBound, midPoint)
            : binaryHelper(arr, element, midPoint, uBound);
    }
}

console.log("even array test");
var array = [1,3,4,5,9];
binaryInsertion(array, 2);
console.log(array);

console.log("odd array test");
var array = [1,3,5,7,9,11,13,15];
binaryInsertion(array, 10);
console.log(array);

console.log("beginning and end test");
var array = [2,3,4,5,9];
binaryInsertion(array, 0);
binaryInsertion(array, 10);
console.log(array);

【讨论】:

  • 智能检测应该低于O(n) - 对于排序数组,它是O(log(n)),使用二进制截断找到正确的索引。
  • @VLAZ 你是对的!感谢您指出这一点,我完全忘记了它。我将它添加到答案中,并将为其添加一些代码(问题已结束,但也许它仍然会帮助一些迷失的灵魂)。
  • 在这里失去灵魂,如果数组以少于 2 个元素开始,则此代码将导致 RangeError: Maximum call stack size exceeded.。这可能不太优雅,但它解决了问题:function binaryInsertion(arr, element) { if (arr.length==0) return arr.push(element); if (arr.length==1) return element &lt; arr[0] ? arr.unshift(element) : arr.push(element); return binaryHelper(arr, element, 0, arr.length - 1); }(抱歉,cmets 中没有代码块。)
猜你喜欢
  • 2012-11-22
  • 2022-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-10
  • 2010-10-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多