PHP二分法

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的連續內存空間, 要求稍微有些高, 海量數據查找以後再說
 
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章