二分查找

最近学习了二分查找算法,总结归纳一下。

 

二分查找算法,也叫做折半查找算法。

下面来说明一下查找的流程:

数字是从1~99的范围,比如要查找23数字。

 

查找次数 查找范围 中间值 判断条件
第一次  0~99 49  49>23
第二次 0~48 24 24>23
第三次 0~23 11 11<23
第四次 12~23  17 17<23
第五次 18~23  20 20<23
第六次 21~23 22 22<23
第七次 23 ==

 

经过7次比较,得到最终等于target值得数字。

 

这个比较得过程就是运用得二分比较得思想,每次都与区间得中间值进行比较大小,根据值得大小情况进行缩小区间范围。

L为最小值

H为最大值(也就是数组得长度减1)

mid为中间值,中间值得计算如下采用了位运算mid = L + (H - L)>>1;

 

二分查找主要针对得是一个有序得数组集合,每次查找根据target值进行缩小范围查找,如果不是有序得,无法判断数据所在区间。

下面总结一下在写代码过程中容易出错得地方:

1、循环退出得条件

     L <= H 而不是 L< H

2、mid取值问题

    有多种写法,我们去例子俩种做一个比较把

     第一种: mid = (L + H) /2; 还要运用取整函数进行取整,如果L 和 H 这个数据比较大的话,两者之和可能会溢出

     第二种:采用位运算计算要比除法运算快的多。 mid = (L + (H - L) >>2); 向右挪一个位置,实际上就是做了一个除2的操作。

3、L 和 H值进行更新的问题

     当 中间值 < target值时,将L挪到 mid +1位置,比较区间为 [mid+1,H]

     当中间值 > target 值时,将H 挪到mid-1位置,比较区间为 [L,mid-1]

     相等时即为target值 结束循环

    

 

以下二分查找的代码:(代码语言为php语言实现的)

1、二分查找target值题代码如下:

$arr = [1, 2, 3, 4, 6, 7, 9];
$target = 8;

function ef($arr, $target, $l, $r)
{
    while ($l <= $r) {
        $mid = $l + (($r - $l) >> 1);
        if ($arr[$mid] > $target) {
            $r = $mid - 1;
        } elseif ($arr[$mid] < $target) {
            $l = $mid + 1;
        } else {
            return 1;
        }
    }
    return -1;
}

$a = ef($arr, $target, 0, 7);

 

2、二分查找扩展题  -- 查找target值第一次出现的位置,会有重复的数据出现

 

$arr = [1, 2, 3, 4, 6, 7, 9, 9, 9, 9];
$target = 9;

function fristTarget($arr, $target)
{
    $n = count($arr);
    $l = 0;
    $r = $n - 1;
    while ($l <= $r) {
        $mid = $l + (($r - $l) >> 1);
        if ($arr[$mid] < $target) {
            $l = $mid + 1;
        } elseif ($arr[$mid] > $target) {
            $r = $mid - 1;
        } elseif ($arr[$mid] == $target) {
            if ($mid == $r) {
                return $mid;
            }
            if ($arr[$mid - 1] == $target) {
                $r = $mid - 1;
            } else {
                return $mid;
            }
        }

    }
    return -1;
}

$a = fristTarget($arr, 9);

 

 

 

 

3、二分查找扩展题-- 查找target值 最后一次出现的位置,会有重复的数据出现

 

$arr = [1, 2, 3, 4, 6, 7, 9, 9, 9, 0];
$target = 9;

function endTarget($arr, $target)
{
    $n = count($arr);
    $l = 0;
    $r = $n - 1;

    while ($l <= $r) {
        $mid = $l + (($r - $l) >> 1);
        if ($arr[$mid] > $target) {
            $r = $mid - 1;
        } elseif ($arr[$mid] < $target) {
            $l = $mid + 1;
        } else {
            if ($mid == $n - 1) {
                return $mid;
            }
            if ($arr[$mid + 1] == $target) {
                $l = $mid + 1;
            }else{
                return $mid;
            }
        }
    }
}

$a = endTarget($arr,9);

 

 

 

 

 

posted @ 2022-01-14 16:41  核桃MM  阅读(191)  评论(0)    收藏  举报