修炼内功---数据结构与算法15---二分法变形1

除了正常的二分查找,还有很多二分查找的变形版本

符合标准的二分查找条件的序列一般是比较理想的情况,如果要查找的元素在序列中有多个怎么办?

在一个给定排序序列中查找第一个等于给定值的元素

其实关键节点就在于在序列中找到值等于待查找元素值时的处理

如果此时 $mid 位置已经到了序列的最左边,不能再往左了,或者序列中索引小于 $mid 的上一个元素值不等于待查找元素值,那么此时 $mid 就是第一个等于待查找元素值的位置,否则还要继续往前找

<?php

/**
 * 二分查找变形版:查找第一个值等于给定值的元素(数组中包含重复数据)
 */
function binary_search($nums, $num)
{
    if (count($nums) <= 1) return 0;

    return binary_search_internal($nums, $num, 0, count($nums) - 1);
}

function binary_search_internal($nums, $num, $low, $high)
{
    if ($low > $high) return -1;

    $mid = floor(($low + $high) / 2);

    if ($num < $nums[$mid]) {
        return binary_search_internal($nums, $num, $low, $mid - 1);
    } elseif ($num > $nums[$mid]) {
        return binary_search_internal($nums, $num, $mid + 1, $high);
    } else {
        if ($mid == 0 || $nums[$mid-1] != $num) {
            return $mid;
        } else {
            return binary_search_internal($nums, $num, $low, $mid - 1);
        }
    }
}

$nums = [1, 2, 3, 3, 4, 5, 6];
$index = binary_search($nums, 3);
print $index;

既然有第一个等于给定值的查询,自然就有最后一个等于给定值的查询

这就是二分查找的第二个变形版本:在给定已排序序列中查找最后一个等于给定值的元素

实现逻辑和上面类似,只需要改动 $num == $nums[$mid] 时的处理逻辑

只是这时的条件变成了 $mid 位置到了序列的最右边,不能再往后了,或者索引大于 $mid 的后一个元素值不等于带查找元素,才返回 $mid,否则,还要继续往后找

<?php

/**
 * 二分查找变形版:查找最后一个值等于给定值的元素(数组中包含重复数据)
 */
function binary_search($nums, $num)
{
    if (count($nums) <= 1) return 0;

    return binary_search_internal($nums, $num, 0, count($nums) - 1);
}

function binary_search_internal($nums, $num, $low, $high)
{
    if ($low > $high) return -1;

    $mid = floor(($low + $high) / 2);

    if ($num < $nums[$mid]) {
        return binary_search_internal($nums, $num, $low, $mid - 1);
    } elseif ($num > $nums[$mid]) {
        return binary_search_internal($nums, $num, $mid + 1, $high);
    } else {
        if ($mid == count($nums) - 1 || $nums[$mid + 1] != $num) {
            return $mid;
        } else {
            return binary_search_internal($nums, $num, $mid + 1, $high);
        }
    }
}

$nums  = [1, 2, 3, 3, 4, 5, 6];
$index = binary_search($nums, 3);
print $index;

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值