1. 题目解析与解题思路
在排序数组中查找元素的第一个和最后一个位置,这道题目看似简单,但隐藏着不少值得深入探讨的细节。作为一名经常刷题的开发者,我发现这道题是理解二分查找边界条件的绝佳案例。
题目要求我们找到一个已排序数组中特定目标值的起始和结束位置。如果目标值不存在于数组中,则返回[-1, -1]。关键在于时间复杂度必须为O(log n),这直接指向了二分查找算法。
1.1 为什么普通二分查找不够用?
传统的二分查找在找到目标值后会立即返回,但这道题需要找到目标值的边界。举个例子,对于数组[5,7,7,8,8,10]和目标值8,普通二分查找可能找到任意一个8的位置就返回了,而我们需要的是第一个8和最后一个8的位置。
提示:处理边界问题时,建议在纸上画出数组和指针移动的过程,这比单纯在脑海中想象要直观得多。
1.2 左右边界查找的核心思路
解决这个问题的关键在于分别实现查找左边界和右边界的函数:
- 查找左边界:即使找到目标值,也继续向左搜索
- 查找右边界:即使找到目标值,也继续向右搜索
这种"继续搜索"的思路是解决边界问题的核心。我在最初实现时也犯了一个常见错误——在找到目标值后就停止搜索,这导致无法正确处理重复元素的情况。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 代码实现与细节分析
2.1 右边界查找实现
让我们先看右边界的查找实现:
cpp复制int RightRange(vector<int>& nums, int target) {
int left = 0;
int right = nums.size()-1; // 采用闭区间[left,right]
int rightRange = -2; // 初始值设为-2,用于特殊判断
while(left <= right) {
int mid = left + (right - left)/2; // 防止溢出
if(nums[mid] <= target) {
left = mid + 1;
rightRange = left - 1; // 记录可能的右边界
}
else {
right = mid
