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

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

所不同的是判断节点不一样了,我们之前的需求都是查找等于给定值

现在变成了大于等于给定值,所以我们要在 $nums[$mid] >= $num 这个判断条件上做文章

思路还是和之前两个变形版本类似

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

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

在给定序列中查找最后一个小于等于给定值的元素

这次的判断节点变成了 $nums[$mid] <= $num

其中 $num 是待查找的元素值,当 $mid 已经是最后一个元素索引,或者 $mid 的后一个元素值大于 $num 则当前 $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 ($nums[$mid] <= $num) {
        if ($mid == count($nums) - 1 || $nums[$mid + 1] > $num) {
            return $mid;
        } else {
            return binary_search_internal($nums, $num, $mid + 1, $high);
        }
    } elseif ($nums[$mid] > $num) {
        return binary_search_internal($nums, $num, $low, $mid - 1);
    }
}

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

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值