1. 题目解析
Leetcode链接:34. 在排序数组中查找元素的第一个和最后一个位置
这个问题的理解其实相当简单,只需看一下示例,基本就能明白其含义了。
核心在于找到给定目标值所在的数组下标区间,设计一个O(logn)的算法。
2. 算法原理
寻找左边界思路:
目标:找到数组中第一个大于或等于目标值的元素的索引。
特点:
- 左边区间
[left, resLeft - 1]
的所有元素都小于target
。 - 右边区间(包括
resLeft
)[resLeft, right]
的所有元素都大于等于target
。
二分查找步骤:
- 初始化
left
和right
为数组的开始和结束索引。 - 计算中间索引
mid
(注意向下取整)。 - 根据
arr[mid]
与target
的关系,调整left
或right
的值。- 如果
arr[mid] < target
,则更新left = mid + 1
。 - 如果
arr[mid] >= target
,则更新right = mid
。
- 如果
- 重复步骤 2 和 3,直到
left > right
。 - 返回
left
或right
(取决于具体实现)。
注意:当 right = mid
时,应向下取整,以防止死循环。
寻找右边界思路:
目标:找到数组中最后一个大于或等于目标值的元素的索引。
特点:
- 左边区间
[left, resRight]
的所有元素都小于等于target
。 - 右边区间
[resRight + 1, right]
的所有元素都大于target
。
二分查找步骤:
- 初始化
left
和right
为数组的开始和结束索引。 - 计算中间索引
mid
(注意向上取整)。 - 根据
arr[mid]
与target
的关系,调整left
或right
的值。- 如果
arr[mid] <= target
,则更新left = mid
。 - 如果
arr[mid] > target
,则更新right = mid - 1
。
- 如果
- 重复步骤 2 和 3,直到
left > right
。 - 返回
right
或left
(取决于具体实现)。
注意:当 right = mid
时,应向上取整,以防止死循环。
通过合理地调整 left
和 right
的值,二分查找可以高效地找到左边界和右边界。
3. 代码编写
class Solution {
public:vector<int> searchRange(vector<int>& nums, int target) {int left = 0, right = nums.size() - 1, begin = -1, end = -1, mid;//找到区间左边界while(left<=right){mid = (left + right)/2;if(nums[mid] > target){right = mid - 1;}else if(nums[mid] < target){left = mid + 1;}else{begin = mid;right--;//right区间左移,使得mid左移,直到到达左区间边界,此时right正好和left重合}}left = 0, right = nums.size() - 1;//找到区间有边界while(left<=right){mid = (left + right)/2;if(nums[mid] > target){right = mid - 1;}else if(nums[mid] < target){left = mid + 1;}else{end = mid;left++;//left区间右移,使得mid右移,直到到达又区间边界,此时left正好和right重合}}return {begin,end};}
};
The Last
嗯,就是这样啦,文章到这里就结束啦,真心感谢你花时间来读。
觉得有点收获的话,不妨给我点个赞吧!
如果发现文章有啥漏洞或错误的地方,欢迎私信我或者在评论里提醒一声~