【算法】二分查找(二)查找边界二分


目录
题目介绍
34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(LeetCode)
给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。
你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。
示例 1:
输入:nums = [5,7,7,8,8,10], target = 8 输出:[3,4]
示例 2:
输入:nums = [5,7,7,8,8,10], target = 6 输出:[-1,-1]
示例 3:
输入:nums = [], target = 0 输出:[-1,-1]
提示:
0 <= nums.length <= 105-109 <= nums[i] <= 109nums是一个非递减数组-109 <= target <= 109
二段性
区域 可划分成 两段性质部分
1.二段搜索
两指针 在各段部分内 中点算 半缩排区域 地 跃段住段 往界点搜索1.1搜索段端点
跃指针与住指针相遇时 算排出 住段部分的端点1.1.1住段的左端点
1.1.2住段的右端点
2.死循环
中点 下次立到 在住段部分的 住指针时,住指针的移动 去原地踏步后,再下次的中点也还不变 继续立住指针 去原地踏步,进入死循环2.1中点偏向left + (right - left) / 2 立 偏左中点left + (right - left + 1) / 2 立 偏右中点
中点 不能 偏向 住段侧 立,否则 最后中点会立到住指针 而进入死循环2.2多余搜索
跃指针与住指针相遇 算排得到结果后 就可停止搜索了,如果此时继续去搜索,left == right的中点 会立到住指针 而进入 原地踏步死循环除非里面增加一个 left == right时 判断nums[left]等不等于target 已找到边界或找不到边界 而return退出,否则left <= right 条件退不出来的3.模板
while(left < right) {
int mid = left + (right - left) / 2; —> 立 偏左中点
if(mid落左跃段) left = mid + 1;
else right = mid; —> mid落右住段
}
while(left < right) {
int mid = left + (right - left + 1) / 2; —> 立 偏右中点
if(mid落左住段) left = mid;
else right = mid - 1; —> mid落右跃段
}
(最上面 + 1,最下面 - 1)4.区别
朴素二分 是 找值所在位置∈边界二分 是 找值范围边界可以通过 找此一个值的边界位置 来找到此值
3.2求段右端点:

3.1求段左端点:

提交代码
public int[] searchRange(int[] nums, int target) { int[] ret = new int[2]; ret[0] = ret[1] = -1; if(nums.length == 0) return ret; // 查找段端点,住段的左端点: [<3] [这里|>=3] (左对应>=) int left = 0, right = nums.length - 1; while(left < right) { // 不能去多余搜索 left == right时的情况,否则会 中点立到住指针 进入死循环 int mid = left + (right - left) / 2; // 中点要偏向跃段部分 即偏左 if(nums[mid] < target) left = mid + 1; // mid落左跃段 else right = mid; // mid落右住段 } if(nums[left] != target) return ret; else ret[0] = left; // 查找段端点,住段的右端点: [<=3|这里] [>3] (右对应<=) // left = 0; // 接下来左指针 可以直接从找到的左端点处开始 对剩下的右半部分 进行二分 查找右端点 right = nums.length - 1; while(left < right) { int mid = left + (right - left + 1) / 2; // 中点不能偏向住段部分 即偏右 // 上面有+1 if(nums[mid] <= target) left = mid; // mid落左住段 else right = mid - 1; // mid落右跃段 // 下面有-1 } ret[1] = left; return ret; }