本题的思路在于,找到第一个重复元素的位置并不难,但是怎么找最后一个位置呢,小编想法是找比目标值大的元素,大一个即可,不论原数组中是否存在比目标值大一个的元素,因为二分里面查找是按照中间位置的元素大小与目标值元素大小进行的,因此如果查找比目标值大一的元素,最终就会找到目标值右边一个的位置,然后我们只需要将该位置减一即可。二分法中每次返回的都是待查找元素最左边的下标。
class Solution {
// lower_bound 返回最小的满足 nums[i] >= target 的 i
// 如果数组为空,或者所有数都 < target,则返回 nums.size()
// 要求 nums 是非递减的,即 nums[i] <= nums[i + 1]
// 闭区间写法
int lower_bound(vector<int> &nums, int target)
{
int left = 0, right = (int) nums.size() - 1; // 闭区间 [left, right]
while (left <= right)
{ // 区间不为空
int mid = right + left / 2;
if (nums[mid] < target)
left = mid + 1; // 范围缩小到 [mid+1, right]
else
right = mid - 1; // 范围缩小到 [left, mid-1]
}
return left; // 或者 right+1
}
public:
vector<int> searchRange(vector<int> &nums, int target)
{
int start = lower_bound(nums, target); // 使用其中一种写法即可
if (start == nums.size() || nums[start] != target)
return {-1, -1};
// 如果 start 存在,那么 end 必定存在,这里是巧妙的地方
// target + 1表示不一定非要找到比目标值大 1 的值,而是根据判断会向右移动,
// 左指针会留在比目标值大一个元素的位置,数值上不一定会大 1 ,但是位置会到想要的地方
int end = lower_bound(nums, target + 1) - 1;
return {start, end};
}
};
博客介绍了用二分法查找数组中重复元素最后位置的思路。先找比目标值大一个的元素,二分查找会返回其最左边下标,该位置减一就是目标元素最后位置,而二分法每次返回的是待查找元素最左边下标。

被折叠的 条评论
为什么被折叠?



