二分算法的前提是排序数组,通过折半查找的方式,将找到目标值的时间复杂度缩小到O(logn)
最主要的3个问题
- 查找某元素即返回索引
- 查找某元素的左边界索引
- 查找某元素的右边界索引
二分算法框架:
// 查找某元素即返回索引
int binarySearch(int num[], int length, int target){
if(length < 1)
return -1;
int left = 0;
int right = length - 1;
// 左右封闭
while(left <= right){
int middle = left + ((right - left) >> 1);
if(num[middle] == target)
return middle;
else if(num[middle] > target)
right = middle - 1;
else if(num[middle] < target)
left = middle + 1;
// 全写else if,不写else,这样更好理解
}
// 找不到就直接返回
return -1;
}
// 查找左边界
int binaryLeftBound(int num[], int length, int target){
if(length < 1)
return -1;
int left = 0;
int right = length - 1;
// 左右封闭法(注意也可以左闭右开)
while(left <= right){
int middle = left + ((right - left) >> 1);
if(num[middle] == target)
// 不着急返回,向左收缩范围
right = middle - 1;
else if(num[middle] > target)
right = middle - 1;
else if(num[middle] < target)
left = middle + 1;
}
// left可能越界
if(left >= length || num[left] != target)
return -1;
return left;
}
// 查找右边界
int binaryRightBound(int num[], int length, int target){
if(length < 1)
return -1;
int left = 0;
int right = length - 1;
// 左右封闭法(注意也可以左闭右开)
while(left <= right){
int middle = left + ((right - left) >> 1);
if(num[middle] == target)
// 不着急返回,向右收缩范围
left = middle + 1;
else if(num[middle] > target)
right = middle - 1;
else if(num[middle] < target)
left = middle + 1;
}
if(right < 0 || num[right] != target)
return -1;
return right;
}