二分搜索原理看似都懂,可是真的让我敲起来,我还真不敢保证写的必定没有bug,甚至陷入bug里不知道怎么改呢.
其实,二分法真的不是那么简单,尤为是二分的各个变种.下面一次介绍各类变种二分法,而且加上个人总结吧.数组
在一个排好序的数组里查找一个key值.code
int search(int *arr, int n, int key) { int left = 0, right = n-1; while(left<=right) { int mid = left + ((right - left) << 1); if (arr[mid] == key) return mid; else if(arr[mid] > key) right = mid - 1; else left = mid + 1; } return -1; }
若是条件变化成, 数组中的数据可能重复,要求范围等于key值最小的下标,或者找出数组中第一个大于(或等于)key值的元素下标,请看下面ast
int searchFirstEqual(int *arr, int n, int key) { int left = 0, right = n-1; while(left<=right) { int mid = (left+right)/2; if(arr[mid] >= key) right = mid - 1; else if(arr[mid] < key) left = mid + 1; } if( left < n && arr[left] == key) return left; return -1; }
int searchLastEqual(int *arr, int n, int key) { int left = 0, right = n-1; while(left<=right) { int mid = (left+right)/2; if(arr[mid] > key) right = mid - 1; else if(arr[mid] <= key) left = mid + 1; } if( right>=0 && arr[right] == key) return right; return -1; }
int searchFirstEqualOrLarger(int *arr, int n, int key) { int left=0, right=n-1; while(left<=right) { int mid = (left+right)/2; if(arr[mid] >= key) right = mid-1; else if (arr[mid] < key) left = mid+1; } return left; }
int searchFirstLarger(int *arr, int n, int key) { int left=0, right=n-1; while(left<=right) { int mid = (left+right)/2; if(arr[mid] > key) right = mid-1; else if (arr[mid] <= key) left = mid+1; } return left; }
int searchLastEqualOrSmaller(int *arr, int n, int key) { int left=0, right=n-1; while(left<=right) { int m = (left+right)/2; if(arr[m] > key) right = m-1; else if (arr[m] <= key) left = m+1; } return right; }
int searchLastSmaller(int *arr, int n, int key) { int left=0, right=n-1; while(left<=right) { int mid = (left+right)/2; if(arr[mid] >= key) right = mid-1; else if (arr[mid] < key) left = mid+1; } return right; }
int search(int *arr, int n, int key) { int left=0, right=n-1; while(left<=right) { int mid = (left+right)/2; if(arr[mid] /****/ key) right = mid-1; else if (arr[mid] /****/ key) left = mid+1; } return /****/; }
其中除了3处/****/以外,其余部分能够说是模板,很简短,用的时候敲出来就好了模板
说到这里,咱们的返回值和等号加在哪里,2个问题都解决了,就能够写完美的二分法啦!
原理