1. 二分查找:如果找到key,结束循环
如果找到key,结束循环。返回mid。
如果找不到key,最终的结束状态会是right < left,并且right + 1 = left。返回-1。
public static int binarySearch(int[] nums,int target,int left, int right) {
//循环条件
while (left <= right) {
//计算mid
int mid = left + ((right - left) >> 1);
if (nums[mid] == target) {
return mid;
}else if (target > nums[mid]) {
//target在右边
left = mid + 1;
} else {
//target在左边
right = mid - 1;
}
}
//边界情况:没有找到该元素,返回 -1
return -1;
}
2. 变种:找到key并不结束循环,最终总是因为right < left结束循环
当数组中不存在key时或找到key并不结束循环,最终的结束状态会是right < left,并且right + 1 = left。
当数组中存在key时,根据二分区间选择的不同,这里又分为两种情况:
1. 比较符号和返回值的变化:
左边情况:target <= nums[mid] 即:等于情况合并到target < nums[mid] right = mid - 1
1)用于找target下边界(第一个target)或第一个大于等于target的值:return left;
2)最后一个小于target的值:return right;
右边情况:target >= nums[mid] 即:等于情况合并到target > nums[mid] left = mid + 1
1)用于找target上边界(最后一个target)即最后一个小于等于target的值:return right;
2)第一个大于target的值:return left;
主体只要分情况更改 target ?= nums[mid] 和return left/right即可。
2. 边界情况的判断:
有时题意会有找不到的边界情况,此时返回-1,要注意边界情况的判断:
1)查找target的上下边界,如不存在返回[-1, -1]
int upper = upperBound(nums,target); //return right
int low = lowerBound(nums,target); //return left
//边界条件:不存在的情况
if (upper < low) {
return new int[]{-1,-1};
}
return new int[]{low,upper};
2)查找第一个与target相等的元素,如不存在返回-1
//arr[right] < key <= arr[left]
//right是最后一个小于key的
//left是第一个大于等于key的
if (left < nums.length && nums[left] == target) {
return left;
}
return -1;
3)查找最后一个与target相等的元素,如不存在返回-1
//arr[right] <= key < arr[left]
//right是最后一个小于等于key的
//left是第一个大于key的
if (right >= 0 && nums[right] == target) {
return right;
}
return -1;
3. 总结
public static int binarySearch(int[] nums,int target,int left, int right) {
//循环条件
while (left <= right) {
//计算mid
int mid = left + ((right - left) >> 1);
if (target ? nums[mid]) { //#### 1
//target在右边
left = mid + 1;
} else {
//target在左边
right = mid - 1;
}
}
//####2: 在查找第一个或最后一个与target相等的元素时,要加上if判断
return ?; //####3: return left or right
//没有找到该元素
return -1;
}
比较符号:左边情况 <=,右边情况 <
返回值:左边情况 right,右边情况 left
边界情况:return -1
reference:
https://www.cnblogs.com/gongpixin/p/6761389.html