---
# System prepended metadata

title: 二分搜尋法（Binaray Search)
tags: [程式設計 II]

---

# 二分搜尋法（Binaray Search)

## 為何要二分搜尋
假設今天有一個由小到大的陣列，但沒有一定的規律性
{1,3,7,8,11,14......,763,5252}
那我想找到 763 這個數字，初學者都會利用

`for(int i = 0; i < sizeof(array)/sizeof(array[0]); i++) `

去找尋
但這會遇到一個問題，如果今天array的大小為10萬
然後又剛好數字是最後一個，不就要跑10萬次
那100萬的情況，大概就是吃TLE
![image](https://hackmd.io/_uploads/BkYxl08Lp.png =50%x)

這時就得用上二分搜尋去縮短時間

## 什麼是二分搜尋 📖cccc

用最大值跟最小值去做判斷不停的壓縮這兩個範圍，直到找到答案
玩過猜數字遊戲吧？
沒玩過也沒關係，稍微解釋這遊戲
今天預設答案為 70 範圍為 1 ~ 100，請你去做猜測
這時
猜：90，官方：比較小，這時你知道範圍縮小為 1 ~ 90
猜：65，官方：比較大，這時你知道範圍縮小為 65 ~ 90
二分搜尋就類似這種做法

## 示範Code
```c=
#include <stdio.h>
#define ma 12
void BinarySearch(int array[], int goal)
{
    int left = 0, right = ma - 1;
    while (left <= right)
    {
        int mid = (left + right) / 2;
        if (array[mid] == goal)
        {
            printf("Find the goal : %d\n", mid);
            break;
        }
        else if (array[mid] > goal)
        {
            right = mid - 1;
        }
        else if (array[mid] < goal)
        {
            left = mid + 1;
        }
    }
    if (left > right)
    {
        printf("No find the answer\n");
    }
}
int main()
{
    int array[ma] = {1, 3, 5, 6, 7, 8, 9, 11, 15, 19, 21};
    BinarySearch(array, 19);
    BinarySearch(array, 10);
    return 0;
}
```

## 幾個問題❓

### 1. 為何要 right = ma - 1
因為陣列大小開12，但電腦是從 0 開始的
所以實際上數字是存放在 0,1,2,3,...,9,10,11

### 2. 為何要 while(left <= right) 而非 while(left < right)
因為當答案剛好在 left == right 時，才不會遺漏掉

### 3. 為何在判斷時，left = mid + 1, right = mid - 1
因為 mid 的位置我們就可以不用在看了

舉例：
當 array[mid] < goal 時
就代表 mid 之前的數字都不用看(包括mid)
因此left = mid + 1

當 array[mid] > goal 時
就代表 mid 之後的數字都不用看(包括mid)
因此left = mid - 1

## 上課練習
[LeetCode](https://leetcode.com/problems/search-insert-position/)
## 參考
[二分搜](https://hackmd.io/@SupportCoding/Binary_search)
[二分搜-2](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)
