数据结构与算法学习之路11--二分查找(下)

121 阅读1分钟

当序列中存在重复的值时二分查找会出现变形,比较典型的有查找第一个等于给定值的元素、查找最后一个等于给定值的元素、查找第一个大于等于给定值的元素、查找最后一个小于等于给定值的元素这四种。

查找第一个等于给定值的元素PHP版

function breach($arr, $value)
{
    $low = 0;
    $height = count($arr)-1;
    while ($low <= $height) {
        $middle = (int)($low + ($height-$low)/2);
        if ($arr[$middle] > $value) {
            $height = $middle-1;
        } elseif ($arr[$middle] < $value) {
            $low = $middle+1;
        } else {
            if ($middle == 0 || $arr[$middle-1] != $value) {
                return $middle;
            } else {
                $height = $middle-1;
            }
        }
    }
    return false;
}

查找最后一个等于给定值的元素PHP版

function breach($arr, $value)
{
    $low = 0;
    $height = count($arr)-1;
    while ($low <= $height) {
        $middle = (int)($low + ($height-$low)/2);
        if ($arr[$middle] > $value) {
            $height = $middle-1;
        } elseif ($arr[$middle] < $value) {
            $low = $middle+1;
        } else {
            if ($middle == count($arr)-1 || $arr[$middle+1] != $value) {
                return $middle;
            } else {
                $low = $middle+1;
            }
        }
    }
    return false;
}

查找第一个大于等于给定值的元素PHP版

function breach($arr, $value)
{
    $low = 0;
    $height = count($arr)-1;
    while ($low <= $height) {
        $middle = (int)($low + ($height-$low)/2);
        if ($arr[$middle] < $value) {
            $low = $middle+1;
        } else {
            if ($middle == count($arr)-1 || $arr[$middle+1] = $value) {
                return $middle;
            } else {
                $low = $middle+1;
            }
        }
    }
    return false;
}

查找最后一个小于等于给定值的元素PHP版

function breach($arr, $value)
{
    $low = 0;
    $height = count($arr)-1;
    while ($low <= $height) {
        $middle = (int)($low + ($height-$low)/2);
        if ($arr[$middle] > $value) {
            $height = $middle-1;
        } else {
            if ($middle == 0 || $arr[$middle-1] = $value) {
                return $middle;
            } else {
                $low = $middle+1;
            }
        }
    }
    return false;
}

变形的二分查找方法需要注意有以下三点:

  • 终止条件
  • 上下界线的更新方法
  • 返回值选择