Binary Search的變型 === [TOC] BS使用在sorted nums,常用於連續的數字中找特定的數字 可以在暴力解O(N)的情況下變成O(logN) ## 基本型 這個條件下nums每個數值是唯一的 值得注意的點: * right要不要包含最後一個元素,還是等於size 我喜歡包含 * while條件l要不要包含r,也就是<還是<= 我喜歡<= * 每次條件判斷時候mid這個數值要不要留著,還是直接捨棄 我喜歡左右都捨棄 * 計算mid有很多種方法, * (l+r)/2 容易overflow * l + (r-l)/2 相較於上一個沒這麼容易overflow ```c= #include <stdio.h> #define size 6 int BS(int nums[], int target) { int l= 0, r= size-1; while(l<= r) { int mid= l+ (r-l)/2; if(nums[mid] == target) return mid; if(nums[mid]< target) l= mid+1; else r= mid-1; } return -1; } int main() { int nums[]= {1,3,5,7,9,10}; int input; while(1) { scanf("%d", &input); printf("input %d is located in %d\n", input, BS(nums, input)); } return 0; } ``` ## nums中的每個元素不唯一,返回最左邊的target 換句話說,我們去找==第一個小於target的數,在把index+1==就是我們要的 這邊假設要找的target存在nums,如果要處理不存在的話,就再看一下找出來的答案是不是要找的target nums[mid]是不是等於target不重要了,我們要找target的左邊那個數,所以我們盡量靠左,讓相等時去推r,最後就r就是第一個小於target的數,r+1就是最左邊的target ```c= #include <stdio.h> #define size 13 int BS(int nums[], int target) { int l= 0, r= size-1; while(l<= r) { int mid= l+ (r-l)/2; if(nums[mid]< target) l= mid+1; else r= mid-1; } return r+1; } int main() { int nums[]= {1,3,3,3,3,3,4,4,5,5,5,10,10}; int input; while(1) { scanf("%d", &input); printf("input %d is located in %d\n", input, BS(nums, input)); } return 0; } ``` ## nums中的每個元素不唯一,返回最右邊的target 換句話說,找到第一個大於target的數再把index-1,==另外的用途是找一個陣列中是否存在大於target的數== 跟第二個相反,我們想往右邊靠,所以nums[mid]==target時,我們去推l,最後l應該會落在最右邊的target,r會落在最右邊的target-1,所以r+1就是我們要的 如果是要判斷是否存在大於target的數,就去判斷r最後是不是超出size ```c= #include <stdio.h> #define size 13 int BS(int nums[], int target) { int l= 0, r= size-1; while(l<= r) { int mid= l+ (r-l)/2; if(nums[mid]<= target) l= mid+1; else r= mid-1; } return r+1; } int main() { int nums[]= {1,3,3,3,3,3,4,4,5,5,5,10,10}; int input; while(1) { scanf("%d", &input); printf("the first greater than input %d number is %d\n", input, nums[BS(nums, input)]); } return 0; } ```