最近又从新拾起了一直很凌乱的二分查找,各类版本,有时候老是很难调对,今天就整理了一下。算法
最基础的二分查找是从非递减序的数组中查找某个元素是否在数组中,若是在的话,随意返回一个位置,若是没有这个元素,返回-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,也就是作区间端点。