之前在 Code complete 中讀到了階梯訪問表的概念 , 寫出了第一版直接遍歷的函式把老專案裡的各種 if else 費率判斷清了個乾淨 .
階梯訪問表適合用在區間大小不固定的情況 , 如利息根據額度變化的需求
/**
* 階梯訪問表 l 左邊界 r右邊界 v 取值
* $table = [
* ['l' => 1500, 'r' => 1500, 'v' => '0.23'],
* ['l' => 2000, 'r' => 2000, 'v' => '0.25'],
* ['l' => 2500, 'r' => 2500, 'v' => '0.29'],
* ['l' => 2700, 'r' => 5000, 'v' => '0.30'],
* ['l' => 5500, 'r' => 7000, 'v' => '0.50'],
* ]
* stairStepAccess($table , 2900) ; // 0.30
*
*
* @param array $table 查詢表
* @param mixed $target 查詢的目標資料
* @return mixed
* @throws Exception
*/
function stairStepAccessIterate($table, $target)
{
foreach ($table as $row) {
if ($row['l'] <= $target && $target <= $row['r']) {
return $row['v'];
}
}
throw new \Exception('stairStepAccess overflow '.$target);
}
然後呢最近每天都有做一道演算法題 , 自然而然的就開始思考起如何優化這個簡單的函式 , 大部分情況下表都是順序排列的, 所以使用了二分查詢重寫了中間部分程式碼
* 階梯訪問表 l 左邊界 r右邊界 v 取值
* $table = [
* ['l' => 1500, 'r' => 1500, 'v' => '0.23'],
* ['l' => 2000, 'r' => 2000, 'v' => '0.25'],
* ['l' => 2500, 'r' => 2500, 'v' => '0.29'],
* ['l' => 2700, 'r' => 5000, 'v' => '0.30'],
* ['l' => 5500, 'r' => 7000, 'v' => '0.50'],
* ]
* stairStepAccess($table , 2900) ; // 0.30
*
*
* @param array $table 查詢表
* @param mixed $target 查詢的目標資料
* @return mixed
* @throws Exception
*/
function stairStepAccess($table, $target)
{
$l = 0;
$r = count($table) - 1;
while ($l <= $r) {
$mid = (int)(($l + $r) / 2);
if ($table[$mid]['l'] <= $target && $target <= $table[$mid]['r']) {
return $table[$mid]['v'];
}
if ($target > $table[$mid]['r']) {
$l = $mid + 1;
} else {
$r = $mid - 1;
}
}
throw new \Exception('stairStepAccess overflow value ' . $target);
}
生成了有 90 萬條資料的表 , 進行 100 萬次查詢後的效能簡單對比
完結撒花 , 演算法撒浪嘿
PS : 尋求有挑戰的工作機會中 , 歡迎聯絡