# 二分搜尋法(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)