class HalfFind { /** * @desc 二分法查找 效率老高了 前提: 必須是有序的數組 * @desc 二分法時間複雜度爲 O(log n) * * @param $nums * @param $val * @return float|int */ function find($nums, $val) { if (count($nums) < 1) { return $nums; } $low = 0; $high = count($nums) - 1; // 易錯點一: $low <= $high, 而不是< while($low <= $high) { // 易錯點二 : 中間位置 // 這種寫法而不是$key = ($low + $high) / 2 是爲了避免當low 和 high都很大的時候求和發生溢出 // 比這種寫法效率更高的寫法是 : $key = ($low + ($high - $low) >> 1) Why? 因爲計算機進行位運算比進行除法運算更快 $key = floor($low + ($high - $low) / 2); if ($nums[$key] == $val) { return $key; }elseif ($nums[$key] < $val) { // 易錯點三: 邊界值變更是 key + 1 或是 key - 1 // 🌰 : 當$low = $high = 3, but $nums[3] != $val, gg, 死循環了 $low = $key + 1; }else{ $high = $key - 1; } } return -1; } // 優點 1 在一定程度上效率高於常數級時間複雜度, 常數級別時間複雜度可以是O(10000) // 優點 2 二分法在pow(2, 32)接近42億個有序元素數組中進行查找, 最多也只進行32次, 牛逼牛逼 // 侷限性 1 必須是順序表結構(數組) 鏈表你試試, 複雜度會很高滴 // 侷限性 2 必須是有序的, 如果對無序的數組進行排序在查找就要視情況而定了, 畢竟最小的排序時間複雜度也要 O(nlogn) // Tips 1 數據量過小, 如10個元素的數組, 直接輪詢就得了, 沒啥差別 // Tips 2 如果數據量不大, 但是每次比對十分耗費時間, 建議二分, 減少比對次數, 提升查找時間 // Tips 3 數據量過大, 不宜二分, 1G的數據, 就意味着要有1G的連續內存空間, 要求稍微有些高, 海量數據查找以後再說 }