Binary Search 二元搜寻找到最接近的答案

Binary Search 二元搜寻找到最接近的答案

找出 大于等于答案(>= target) 的索引位置,最后回传 左指标位置 left 就是要找的答案

程式范例

JavaScript

function BinarySearch(searchNumberArray, searchNumber) {
    // 左侧指标
    var leftNumberPointer = 0;
    // 右侧指标
    var rightNumberPointer = searchNumberArray.length - 1;
    while (leftNumberPointer <= rightNumberPointer) {
        // 中间指标
        var middleNumberPointer = Math.floor((rightNumberPointer + leftNumberPointer) / 2);
        // 中间指标数字
        var middleNumber = searchNumberArray[middleNumberPointer];
        if (searchNumber == middleNumber) {
            // 如果「要找的数字」与「中间指标数字」相同
            // 找到了,回传这个数字指标位置
            return middleNumberPointer;
        }
        else if (searchNumber < middleNumber) {
            // 如果「要找的数字」小于「中间指标数字」
            // 表示「中间指标」右边的所有数字都"大于"「要找的数字」
            // 所以将「右侧指标」移动到目前「中间指标 - 1」的位置
            rightNumberPointer = middleNumberPointer - 1;
        }
        else {
            // 如果「要找的数字」大于「中间指标数字」
            // 表示「中间指标」左边的所有数字都"小于"「要找的数字」
            // 所以将「左侧指标」移动到目前「中间指标 + 1」的位置
            leftNumberPointer = middleNumberPointer + 1;
        }
    }

    // 如果都没有找到,回传最接近的指标
    return leftNumberPointer;
}

TypeScript

function BinarySearch(searchNumberArray: number[], searchNumber: number){
    // 左侧指标
    let leftNumberPointer: number = 0;
    // 右侧指标
    let rightNumberPointer: number = searchNumberArray.length - 1;

    while (leftNumberPointer <= rightNumberPointer) {
        // 中间指标
        let middleNumberPointer = Math.floor((rightNumberPointer + leftNumberPointer) / 2);
        // 中间指标数字
        let middleNumber = searchNumberArray[middleNumberPointer];
        if (searchNumber == middleNumber) {
            // 如果「要找的数字」与「中间指标数字」相同
            // 找到了,回传这个数字指标位置
            return middleNumberPointer;
        } else if (searchNumber < middleNumber) {
            // 如果「要找的数字」小于「中间指标数字」
            // 表示「中间指标」右边的所有数字都"大于"「要找的数字」
            // 所以将「右侧指标」移动到目前「中间指标 - 1」的位置
            rightNumberPointer = middleNumberPointer - 1;
        } else {
            // 如果「要找的数字」大于「中间指标数字」
            // 表示「中间指标」左边的所有数字都"小于"「要找的数字」
            // 所以将「左侧指标」移动到目前「中间指标 + 1」的位置
            leftNumberPointer = middleNumberPointer + 1;
        }
    }

    // 如果都没有找到,回传最接近的指标
    return leftNumberPointer;
}

说明

leftright 代表着可能含有答案的闭区间,所以答案一定在这个范围内

对任何一个数字,假如一直找不到,这个区间会不断减小,直到走到 left == right ,此时区间内只剩下 1 个数字。

有可能最终大于等于、或小于我们要找的 target,最接近的答案表示没有 等于,只有可能是 大于小于

最后的左右指标区间数值,大于要找的数字

最后左右指标数字 6 大于 要找的数字 5.5

索引 0 1 2 3 4 5 6 7 8 9
数字阵列 0 1 2 3 4 5 6 7 8 9
指标位置 左指标 == 右指标

如果大于 target,我们会让 right = mid - 1,而 left 不变

left 继续停留在我们想要的位置上

索引 0 1 2 3 4 5 6 7 8 9
数字阵列 0 1 2 3 4 5 6 7 8 9
指标位置 右指标 左指标

最后的左右指标区间数值,小于要找的数字

最后左右指标数字 6 小于 要找的数字 6.5

索引 0 1 2 3 4 5 6 7 8 9
数字阵列 0 1 2 3 4 5 6 7 8 9
指标位置 左指标 == 右指标

如果小于 target,我们会让 left = mid + 1right 不变

刚好把 left 移到我们想要的位置上

索引 0 1 2 3 4 5 6 7 8 9
数字阵列 0 1 2 3 4 5 6 7 8 9
指标位置 右指标 左指标

最后的左右指标区间数值,小于要找的数字,数值比阵列大

最后左右指标数字 9 小于 要找的数字 99

索引 0 1 2 3 4 5 6 7 8 9
数字阵列 0 1 2 3 4 5 6 7 8 9
指标位置 左指标 == 右指标

如果小于 target,我们会让 left = mid + 1right 不变

刚好把 left 移到我们想要的位置上

索引 0 1 2 3 4 5 6 7 8 9 10
数字阵列 0 1 2 3 4 5 6 7 8 9
指标位置 右指标 左指标

找出 大于等于答案(>= target) 的索引位置,而阵列中都没有这个数字,所以 left 会超出阵列 1 格

最后的左右指标区间数值,大于要找的数字,数值比阵列小

最后左右指标数字 6 大于 要找的数字 -1

索引 0 1 2 3 4 5 6 7 8 9
数字阵列 0 1 2 3 4 5 6 7 8 9
指标位置 左指标 == 右指标

如果大于 target,我们会让 right = mid - 1,而 left 不变

left 继续停留在我们想要的位置上

索引 -1 0 1 2 3 4 5 6 7 8 9
数字阵列 0 1 2 3 4 5 6 7 8 9
指标位置 右指标 左指标

参考资料