二分查找(1.22)
这里主要是对二分查找算法对于寻找左右侧边界问题的应用,关于二分查找的详细介绍,可以看 我写了首诗,把二分搜索算法变成了默写题。因为文章中对于左右侧边界并未做详细介绍,所以在这补充下知识点。
左侧边界:
-
如果数组中存在重复的数据
target
,那么target
第一个出现的位置就是target
的左侧边界。 -
如果数组中不存在重复的target
值,那么第一个比target
大的值的前一个位置就是左侧边界。(有点绕,但是事实的确如此,只是我现在对于这个问题思考较浅,只能这样描述)
右侧边界:
- 如果数组中存在重复的数据
target
,那么target
最后一个出现的位置就是target
的右侧边界。
现在用两种区间判定方案来处理左右侧边界。
寻找左侧边界
(左闭右开):
public static int left_bound(int[] nums, int target){
int left = 0;
int right = nums.length;
while (left < right){
int mid = left + (right - left)/2;
if(nums[mid] == target){//1.mid就是左侧边界 2.mid左侧还有重复target
right = mid;//缩小左侧查询区间
}else if(nums[mid] < target){
left = mid + 1;
}else if(nums[mid] > target){
right = mid;
}
}
if(left == nums.length) return -1;
return (nums[left] == target) left : -1;
}
(左闭右闭)
public static int left_bound(int[] nums, int target){
int left = 0;
int right = nums.length -1;
while (left <= right){
int mid = left + (right - left)/2;
if(nums[mid] == target){//1.mid就是左侧边界 2.mid左侧还有重复target
right = mid -1;//缩小左侧查询区间
}else if(nums[mid] < target){
left = mid + 1;
}else if(nums[mid] > target){
right = mid -1;
}
}
if(left == nums.length) return -1;
return (nums[left] == target) left : -1;
}
寻找右侧边界
(左闭右开)
public static int right_bound(int[] nums, int target){
int left = 0;
int right = nums.length;
while (left < right){
int mid = left + (right - left)/2;
if(nums[mid] == target){
left = mid + 1;
}else if(nums[mid] < target){
left = mid + 1;
}else if(nums[mid] > target){
right = mid;
}
}
}
(左闭右闭)
public static int right_bound(int[] nums, int target){
int left = 0;
int right = nums.length -1;
while (left <= right){
int mid = left + (right - left)/2;
if(nums[mid] == target){
left = mid + 1;
}else if(nums[mid] < target){
left = mid + 1;
}else if(nums[mid] > target){
right = mid -1;
}
}
if((left - 1)<0) return -1;
return nums[left -1] == target ? (left -1) : -1;
}