最近又從新拾起了一直很凌亂的二分查找,各類版本,有時候老是很難調對,今天就整理了一下。算法
最基礎的二分查找是從非遞減序的數組中查找某個元素是否在數組中,若是在的話,隨意返回一個位置,若是沒有這個元素,返回-1。那麼就有了下面這個基礎的算法數組
//查找目標元素在數組中的位置,任意一個均可以,若是沒有返回-1 int Binary_search(int *arr, int n, int val) { int l = 0; int r = n - 1; while (l <= r) { int mid = (l + r) >> 1; if (arr[mid] == val) return mid; if (arr[mid] < val) l = mid + 1; else r = mid - 1; } return -1; }
而後下面關於二分查找的變種比較多了,下面主要列出來一些經常使用的變種函數
1.查找一個大於等於目標元素的位置,等同於lower_bound()函數spa
//查找第一個大於等於目標元素的位置, 等同於lower_bound(); int Binary_search_first_greater_or_equal(int *arr, int n, int val) { int l = 0; int r = n - 1; while (l <= r) { int mid = (l + r) >> 1; if (arr[mid] < val) l = mid + 1; else r = mid - 1; } return l; }
這個主要是去掉了等於的時候直接返回,之因此用小於號而不是小於等因而由於若是若是arr[mid]比要找的元素小的話,大於等於他的元素必定在他的右邊,而若是是等於他的話,可能在他的左邊,大於他天然在左邊。code
2. 查找一個大於目標元素的位置,等同於upper_bound()blog
//查找第一個大於目標元素的位置, 等同於upper_bound(); int Binary_search_first_greater(int *arr, int n, int val) { int l = 0; int r = n - 1; while (l <= r) { int mid = (l + r) >> 1; if (arr[mid] <= val) l = mid + 1; else r = mid - 1; } return l; }
由於要返回大於他的,那麼當arr[mid] == val的時候,繼續往右找。it
3.查找目標元素的第一個位置ast
//查找目標元素的第一個位置,左閉右開區間 int Binary_search_first_pos(int *arr, int n, int val) { int l = 0; int r = n - 1; while (l <= r) { int mid = (l + r) >> 1; if (arr[mid] < val) l = mid + 1; else r = mid - 1; } return (l < n && arr[l] == val) ? l : -1; }
基本上就是查找大於等於元素的程序,只不過在最後加了一個判斷,看看是否等於要找到那個值class
4.查找目標元素的最後一個位置基礎
int Binary_search_last_positon(int *arr, int n, int val)//n is the size of arr { int l = 0; int r = n - 1; while (l <= r) { int mid = (l + r) >> 1; if (arr[mid] > val) r = mid - 1; else l = mid + 1; } if (l >= n && arr[l - 1] != val) return -1;//若找到最後,而且最後元素的值與目標元素不一樣,返回-1 return (l - 1 >= 0 && arr[l - 1] == val) ? l - 1 : -1; }
若arr[mid] > val,那麼天然必定在左邊,若是等於val,有可能在右邊,由於我是找最右的,因此,仍是要繼續往右找
以上全部的返回都是l,也就是作區間端點。