Binary Search 二元搜尋常見問題
Binary Search 二元搜尋常見問題
中間指標切分點算法
| 索引 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
|---|---|---|---|---|---|---|---|---|---|---|
| 指標位置 | 左指標 | 右指標 |
取中間偏左的數字
- 中間指標 左方數字 個數
小於或等於右方數字 個數
公式:
(左指標 + 右指標) / 2,無條件捨去左指標+(右指標 - 左指標) / 2,無條件捨去
// 公式 1
let middleNumberPointer = Math.floor((rightNumberPointer + leftNumberPointer) / 2);
// 公式 2
let middleNumberPointer = leftNumberPointer + Math.floor((rightNumberPointer - leftNumberPointer) / 2);
偶數陣列
中間指標 左方數字 個數
小於右方數字 個數
e.g. [0,1,2,3,4,5,6,7,8,9]
(0 + 9) / 2 = 4.5,無條件捨去為40+(9 - 0) / 2 = 4.5,無條件捨去為4
| 索引 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
|---|---|---|---|---|---|---|---|---|---|---|
| 指標位置 | 左指標 | 中間指標 | 右指標 |
奇數陣列
中間指標 左方數字 個數
等於右方數字 個數
e.g. [0,1,2,3,4,5,6,7,8]
(0 + 8) / 2 = 4,無條件捨去為40+(8 - 0) / 2 = 4,無條件捨去為4
| 索引 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|---|---|---|---|---|---|---|---|---|---|
| 指標位置 | 左指標 | 中間指標 | 右指標 |
while 迴圈判斷式 left <= right
區間定義
| 索引 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 說明 |
|---|---|---|---|---|---|---|---|---|---|---|---|
[3, 5] 閉區間 |
3 | 4 | 5 | 閉區間 [x, y]:包含 x, y |
|||||||
(4, 9) 開區間 |
5 | 6 | 7 | 8 | 開區間 (x, y):不包含 x, y |
||||||
[1, 6) 左閉右開區間 |
1 | 2 | 3 | 4 | 5 | 左閉右開區間 [x, y):包含 x, 不包含 y |
Binary Search 的寫法中的 left 與 right 代表的就是:答案還有可能存在的區間的兩端點,這是個 閉區間 [x, y]
所以當 left == right 的時候,代表可能答案會在 [3,3] 之間,且區間裡只有 1 個元素,但不確定這個元素是不是要找的答案,所以要再判斷一次
因此 while 的判斷式會是 <= 而非 <。
中間指標移動方式,為什麼是 right = mid - 1 跟 left = mid + 1
因為我們要的答案是 閉區間,假如 mid 不是答案,那 mid 必須被排除,需要直接捨棄
當要的答案在左側,則會用 [left, mid-1] 當作新的區間,左邊指標不動,移動右側指標
當要的答案在右側,則會用 [mid+1, right] 當作新的區間,右邊指標不動,移動左側指標