二分查找(Binary Search)要求數組必須有序。每次將查找範圍縮小一半,時間複雜度 O(log n),遠優於線性查找 O(n)。適用於大規模有序數據檢索。
<?php
header('Content-Type: text/html; charset=utf-8');
$arr = [2, 33, 22, 1, 323, 321, 28, 36, 90, 123];
sort($arr); // 必須先排序
echo "排序後數組: " . implode(', ', $arr) . "\n";
$target = 321;
$index = binarySearch($arr, $target);
echo "目標 $target 在索引: $index\n";
/**
* 二分查找迭代實現
* @param array $arr 有序數組
* @param mixed $key 查找目標
* @return int|false 索引位置或 false
*/
function binarySearch($arr, $key) {
$start = 0;
$end = count($arr) - 1;
while ($start <= $end) {
$mid = (int)(($start + $end) / 2);
echo "檢查中間索引 $mid, 值: {$arr[$mid]}\n";
if ($arr[$mid] == $key) {
return $mid;
} elseif ($arr[$mid] < $key) {
$start = $mid + 1; // 目標在右半部分
} else {
$end = $mid - 1; // 目標在左半部分
}
}
return false; // 未找到
}
?>
<?php
/**
* 二分查找遞歸實現
* @param array $array 有序數組
* @param mixed $k 查找目標
* @param int $low 查找範圍下界
* @param int $high 查找範圍上界
* @return int 索引位置或 -1
*/
function binarySearchRecursive($array, $k, $low = 0, $high = 0) {
// 首次調用初始化 high
if ($high === 0 && count($array) > 0) {
$high = count($array) - 1;
}
if ($low <= $high) {
$mid = intval(($low + $high) / 2);
if ($array[$mid] == $key) {
return $mid;
} elseif ($k < $array[$mid]) {
return binarySearchRecursive($array, $k, $low, $mid - 1);
} else {
return binarySearchRecursive($array, $k, $mid + 1, $high);
}
}
return -1; // 未找到
}
// 測試
$array = [4, 5, 7, 8, 9, 10];
echo binarySearchRecursive($array, 8); // 輸出 3
?>
($low + $high) >> 1 或 intval(($low + $high) / 2),防止大數組溢出(PHP 整數無上限,但其他語言需用 low + (high - low) / 2)$start <= $end 而非 <,確保單元素數組可被檢查false 或 -1 表示未找到,避免與索引 0 混淆=== 避免 "123" == 123 導致誤判// 查找第一個 >= target 的位置(下界)
function lowerBound($arr, $target) {
$low = 0; $high = count($arr);
while ($low < $high) {
$mid = ($low + $high) >> 1;
if ($arr[$mid] < $target) $low = $mid + 1;
else $high = $mid;
}
return $low;
}
// 查找第一個 > target 的位置(上界)
function upperBound($arr, $target) {
$low = 0; $high = count($arr);
while ($low < $high) {
$mid = ($low + $high) >> 1;
if ($arr[$mid] <= $target) $low = $mid + 1;
else $high = $mid;
}
return $low;
}
// 統計目標值出現次數
$count = upperBound($arr, $target) - lowerBound($arr, $target);
$arr = range(1, 1000000); // 100萬有序數據 $target = 999999; $start = microtime(true); for ($i = 0; $i < 10000; $i++) binarySearch($arr, $target); echo "迭代版 10000次耗時: " . (microtime(true) - $start) . "s\n"; $start = microtime(true); for ($i = 0; $i < 10000; $i++) binarySearchRecursive($arr, $target); echo "遞歸版 10000次耗時: " . (microtime(true) - $start) . "s\n"; /* 典型輸出: 迭代版 10000次耗時: 0.045s 遞歸版 10000次耗時: 0.062s */
掌握二分查找的正確實現與變體,是程序員處理有序數據高效檢索的基本功,面試高頻考點,實戰價值極高。