当序列中存在重复的值时二分查找会出现变形,比较典型的有查找第一个等于给定值的元素、查找最后一个等于给定值的元素、查找第一个大于等于给定值的元素、查找最后一个小于等于给定值的元素这四种。
查找第一个等于给定值的元素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;
}
变形的二分查找方法需要注意有以下三点:
- 终止条件
- 上下界线的更新方法
- 返回值选择