Javascript 区间范围插入区间而不合并现有区间

Javascript 区间范围插入区间而不合并现有区间,javascript,algorithm,Javascript,Algorithm,问题描述: 其想法是在现有间隔中插入新间隔,新间隔不会与现有间隔合并,而是填补间隔之间缺失的间隙。(这不是区间合并问题) 例如,将区间[0,7]插入区间[[0,1],[3,5]]将产生新的区间,其间隙将填充[[0,1],[1,3],[3,5],[5,7]] 区间范围已从最小到较大排序[[0,1],[3,5] 我目前的解决方案有点“坏”,我最终使用了太多的if检查来覆盖一些特殊情况,这使得一切比需要的更复杂。我正在寻找更好的方法来简化条件部分。在代码的底部包括测试用例,以及解决方案失败的情况 我的

问题描述: 其想法是在现有间隔中插入新间隔,新间隔不会与现有间隔合并,而是填补间隔之间缺失的间隙。(这不是区间合并问题)

例如,将区间[0,7]插入区间[[0,1],[3,5]]将产生新的区间,其间隙将填充[[0,1],[1,3],[3,5],[5,7]]

区间范围已从最小到较大排序
[[0,1],[3,5]

我目前的解决方案有点“坏”,我最终使用了太多的if检查来覆盖一些特殊情况,这使得一切比需要的更复杂。我正在寻找更好的方法来简化条件部分。在代码的底部包括测试用例,以及解决方案失败的情况

我的算法失败并产生错误结果的测试用例:

assert.deepEqual( // Broken
    insertIntervalSec([[1, 5], [7, 10]], [4, 12]),
    [[1, 5], [5, 7], [7, 10], [10, 12]],
);
assert.deepEqual(insertIntervalSec([[1, 1]], [1, 3]), [[1, 3]]); // Broken

function isOverLapping(a, b) {
    return Math.max(a[0], b[0]) <= Math.min(a[1], b[1]);
}

function insertIntervalSec(arr, interval) {
    const result = [];
    let i = 0;

    const contains = (a, b) => {
        return a[0] >= b[0] && a[1] <= b[1]
    };

    if (arr.length <= 0) {
        result.push(interval);
        return result;
    }
    if (arr.length === 1 && contains(interval, arr[0])) {
        result.push(interval);
        return result;
    }

    // Start point
    if (interval[1] >= arr[0][0] && isOverLapping(interval, arr[0])) {
        result.push([interval[0], arr[0][0]]);
    } else if (interval[1] <= arr[0][0]) {
        result.push([interval[0], Math.min(interval[1], arr[0][0])]);
    }

    while (i < arr.length) {
        const current = arr[i];
        result.push(arr[i]);

        if (!contains(interval, arr[i]) && isOverLapping(arr[i], interval)) {
            const next = arr[i + 1];

            // Special handling for the last item
            if (next !== undefined) {
                if (interval[1] > current[1]) {
                    result.push([current[1], next[0]]);
                }
            } else {
                if (interval[0] <= current[0] && interval[1] <= current[1]) {
                    // TODO: No action
                } else if (interval[0] >= current[0] || interval[1] >= current[0]) {
                    result.push([current[1], interval[1]]);
                }
            }
        }
        i++;
    }

    // End point
    const len = arr.length;
    const last = arr[len - 1];
    if (last[1] <= interval[0] && !isOverLapping(last, interval)) {
        result.push(interval);
    }

    return result;
}

assert.deepEqual(
    insertIntervalSec([[1, 5], [10, 15], [20, 25]], [12, 27]),
    [[1, 5], [10, 15], [15, 20], [20, 25], [25, 27]]
);

assert.deepEqual(
    insertIntervalSec([[1, 5], [10, 15], [20, 25]], [-3, 0]),
    [[-3, 0], [1, 5], [10, 15], [20, 25]]
);

assert.deepEqual(
    insertIntervalSec([[1, 5], [10, 15], [20, 25]], [-3, 3]),
    [[-3, 1], [1, 5], [10, 15], [20, 25]]
);

assert.deepEqual(
    insertIntervalSec([[0, 5], [10, 15], [20, 25]], [15, 15]),
    [[0, 5], [10, 15], [20, 25]]
);
assert.deepEqual(
    insertIntervalSec([[0, 5], [10, 15], [20, 25]], [20, 21]),
    [[0, 5], [10, 15], [20, 25]]
);
assert.deepEqual(
    insertIntervalSec([[0, 5], [10, 15], [20, 25]], [26, 27]),
    [[0, 5], [10, 15], [20, 25], [26, 27]]
);
assert.deepEqual(
    insertIntervalSec([[0, 5], [10, 15], [20, 25]], [25, 27]),
    [[0, 5], [10, 15], [20, 25], [25, 27]]
);
assert.deepEqual(insertIntervalSec([], [25, 27]), [[25, 27]]);
assert.deepEqual(insertIntervalSec([[1, 1]], [1, 1]), [[1, 1]]);
assert.deepEqual( // Broken
    insertIntervalSec([[1, 5], [7, 10]], [4, 12]),
    [[1, 5], [5, 7], [7, 10], [10, 12]],
);
assert.deepEqual(insertIntervalSec([[1, 1]], [1, 3]), [[1, 3]]); // Broken

assert.deepEqual(
    insertIntervalSec2([[5, 5]], [6, 6]),
    [[5, 5], [6, 6]]
);

assert.deepEqual(
    insertIntervalSec2([[1, 3]], [6, 6]),
    [[1, 3], [6, 6]]
);
assert.deepEqual(//断开)
插入区间([1,5],[7,10],[4,12]),
[[1, 5], [5, 7], [7, 10], [10, 12]],
);
assert.deepEqual(insertIntervalSec([[1,1]],[1,3]),[[1,3]]);//破碎的
功能重叠(a、b){
返回Math.max(a[0],b[0]){

返回一个[0]>=b[0]&&a[1],除了最后一个测试用例(请参见问题注释),它通过了所有测试。基本思想是您只需跟踪
start
变量,该变量指示插入范围的使用位置。这允许您将其缩小到三种情况:

  • 插入的间隔完全位于当前项的前面
  • 迭代中的当前项在插入的间隔之前完全匹配
  • 迭代中的项重叠
  • 迭代项目后,您可以检查插入的范围是否还有要插入的内容:

    函数插入intervalsec(arr,insert){
    让开始=插入[0]
    让res=[]
    对于(i=0;iconsole.log(insertIntervalSec([[1,5],[10,15],[20,25],[-2,27])
    我不确定您的上一个测试用例是否与在范围列表中插入元素的想法一致。在其他情况下,原始列表中的所有项目都出现在输出中,但在最后一个案例中没有。结果似乎应该是
    [[1,1],[1,3]]
    @MarkMeyer事实上你是对的,是的[1,3]也应该被附加。这是一个固定的解决方案。还忘了提到间隔的开始和结束可能是相同的,包括测试用例以及示例
    insertIntervalSec2([[5,5]],[6,6])->[[5,5],[6,6]]