1.题目解析
题目来源:在排序数组中查找元素的第一个和最后一个位置——力扣
测试用例
2.算法原理
查找左端点
此时根据二段性,需要将数组分为大于target与小于target两部分,然后取出中点位置判断此时中点位置的值与target的大小关系,如果大于等于target则将right指针指向mid位置,反之小于则将left指针指向mid+1位置,以此类推最终二者相交于左端点的位置
细节处理
1.如何确定循环条件
2.如何确定中点位置
解决方法:
1.这里有两个条件:left<=right 与 left<right,因为我们前面知道当left=right时就直接返回了结果,所以不必进入循环,则不可以使用等于作为循环条件,会导致死循环,则选择第二种
2.中点也有两种选择:mid = left+(right-left)/2 与 mid = left+(right-left+1)/2,一个是向上取整一个是向下取整,这里我们使用极端情况:数组中只有两个数据,left指向第一个,right指向第二个,当我们选择第二个时right会保持不变,也就无法与left相交,会导致死循环,所以选择第一个取中点条件
查找右端点
此时根据二段性,需要将数组分为大于target与小于target两部分,然后取出中点位置判断此时中点位置的值与target的大小关系,如果小于等于target则将left指针指向mid位置,反之大于则将right指针指向mid-1位置,以此类推最终二者相交于左端点的位置
细节处理
1.如何确定循环条件
2.如何确定中点位置
解决方法:
1.这里有两个条件:left<=right 与 left<right,因为我们前面知道当left=right时就直接返回了结果,所以不必进入循环,则不可以使用等于作为循环条件,会导致死循环,则选择第二种
2.中点也有两种选择:mid = left+(right-left)/2 与 mid = left+(right-left+1)/2,一个是向上取整一个是向下取整,这里我们使用极端情况:数组中只有两个数据,left指向第一个,right指向第二个,当我们选择第一个时left会保持不变,也就无法与right相交,会导致死循环,所以选择第二个取中点条件
3.实战代码
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target)
{
int left = 0,right = nums.size() - 1;
int begin = 0,end = 0;
//判断特殊情况
if(nums.size() == 0)
{
return {-1,-1};
}
//查找左端点
while(left < right)
{
//向下取整,避免死循环
int mid = left + (right - left) / 2;
if(nums[mid] >= target)
{
right = mid;
}
else
{
left = mid + 1;
}
}
if(nums[left] != target)
{
return {-1,-1};
}
begin = left;
//查找右端点
//左端点已经找到,不必更新左端点
right = nums.size() - 1;
while(left < right)
{
//向上取整避免死循环
int mid = left + (right - left + 1) / 2;
if(nums[mid] <= target)
{
left = mid;
}
else
{
right = mid - 1;
}
}
end = right;
return {begin,end};
}
};