算法学习:二分查找
本文于 434 天之前发表,文中内容可能已经过时。
一、 原则
1. 区间:左右闭区间
2. while结束设定为<=
3. 左右界更新都为mid上下1
二分查找可以设定左闭右开的写法,也可以左右都是闭区间,这里设定后者
在1的设定下,如果left=right,即当前搜索区间长度为1,如果while里面不是<=二是严格<,那么该长度为1的区间就不会搜索,出现遗漏
在1,2的设定之下,必须让left、right的更新机制在循环结束后,right在left的左边,即每次更新right与left必须都不能为mid,因为mid可能 在区间长度为1或者2的时候mid等于其中的left,必须使得right与left有机制在更新时不能一直等于mid,故有原则3
二、三种情况
2.1 直接找元素
int searchBinary(int[] nums, int target) {
//原则1 左右闭区间
int left = 0, right = nums.length - 1;
//原则2 while结束条件为<=
while (left <= right) {
int mid = left + ((right - left) >> 1);
if (nums[mid] == target) {
return mid;
} else if (nums[mid] < target) {
//原则3 左右界更新为mid加减1
left = mid + 1;
} else {
//原则3 左右界更新为mid加减1
right = mid - 1;
}
}
return -1;
}
2.2 寻找左右边界
给定有序数组
如何找第一个2出现的下标或者最后一个2出现的下标
- 找第一个:找左边界
int searchLeftBound(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while (left <= right) {
int mid = left + ((right - left) >> 1);
if (nums[mid] == target) {
right = mid - 1; // 收缩右边界
} else if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
// 越界检查,不存在检查
if (left >= nums.length || nums[left] != target) {
return -1;
}
return left;
}
- 找最后一个:找右边界
int searchRightBound(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while (left <= right) {
int mid = left + ((right - left) >> 1);
if (nums[mid] == target) {
left = mid + 1; // 收缩左边界
} else if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
if (right < 0 || nums[right] != target) {
return -1;
}
return right;
}