---
# System prepended metadata

title: 二元搜尋法

---

# 二元搜尋法

參考網站 
https://ithelp.ithome.com.tw/articles/10213268

https://medium.com/appworks-school/binary-search-%E9%82%A3%E4%BA%9B%E8%97%8F%E5%9C%A8%E7%B4%B0%E7%AF%80%E8%A3%A1%E7%9A%84%E9%AD%94%E9%AC%BC-%E4%B8%80-%E5%9F%BA%E7%A4%8E%E4%BB%8B%E7%B4%B9-dd2cd804aee1
---

> 二元搜尋法前有個前提，來先排序，
> 如果還沒排序可用.sort() 來排序

```python
!/usr/bin/env python3
# -*- coding: utf-8 -*-

def binary_search(data, key):
    low = 0
    high = len(data)-1
    while low <= high:
        mid = int((low + high) / 2)
        if key == data[mid]:
            return mid
        elif key > data[mid]:
            low = mid + 1
        else:
            high = mid - 1
    return -1

data = [1, 9, 2, 7, 4, 10, 3, 8, 5, 6]
key = 7
data.sort()
print(data)
ret = binary_search(data, key)
if ret == -1:
    print('找不到')
else:
    print('找到索引值' + str(ret))
```

## 觀念

a. [3, 5]: 閉區間，代表 3, 4, 5 （包含 3、5）

b. (4, 9): 開區間，代表 5, 6, 7, 8 （不包含 4、9）

c. [1, 6): 左閉右開區間，代表 1, 2, 3, 4, 5 （包含 1、卻不包含 6 )

> 
> 

## **問題**

1. 最上面的 while 迴圈裡面，為什麼我們要寫 left <= right，不能只寫 left < right 嗎？或說，當 left == right 時，需要繼續嗎？
2. right 的起始點為什麼是 array 的長度 -1，不能直接是 array 長度嗎？
3. 中間判斷邊界移動時，為什麼是 right = mid-1 跟 left = mid+1，如果不要 -1 跟 +1 或只有其中一邊+-1，會出錯嗎？

## **解答**

現在我們可以來回答上面三個問題了，問題的答案其實都是一樣的：因為我們定義的 left 與 right 是**閉區間**，也就是包含 left 端點與 right 端點。

問題 1 的答案：當我們 left == right 的那一刻，例如 left == 3、right == 3 好了，那代表可能答案會在 [3,3] 之間，這是個合理的區間，且區間裡只有 3 一個元素，所以當然要再跑一次，確定他是不是我們要的答案，因此 while 的判斷式會是 <= 而非 <。

問題 3 的答案：為什麼要 +-1，同理，因為我們要的答案是**閉區間**，假如 mid 不是答案(因為我們的if else 判斷式已經有一個是判斷是不是Mid==key 了，所以假設會走到另外兩個分支，則必定mid ≠key )，那 mid 必須被排除在**可能是答案的區間**裡，因此不需要再考慮他，直接用 [left, mid-1] 或 [mid+1, right] 當成新的區間即可。

問題 2 的答案：需要一點細心觀察，假如今天我們把 right 定義成 array 長度，也就是”最大的可能 index” + 1 的位置上，首先當然違反了閉區間的原則，因為”最大的可能 index” + 1 不可能是答案，不然就超出 array 範圍了。實際操作時，假如我們的 target 大於 array 裡面最大元素的值，例如 target = 11，我的左邊界就會不停的往右移動 mid+1, mid+1,…，最終他會跑到 left == right，且兩個都停在最大的 index +1，還記得 left == right 的時候我們要再跑一次，而此時 mid 的計算方式會讓我們得出 mid == left 的結果，最終我們的 nums[mid] 就會訪問一個超出範圍的位置，這顯然是很危險的，有些程式語言直接報錯，有的則會給你任意可能的回答，讓你以為沒問題，其實更加危險。