代码比较长,是因为想法比较简单。
解题思路
三步走:
- 用二分法找到target
- 用二分法找到左边界
- 用二分法找到右边界
第1步使用了while形式的二分法,后两步使用了递归形式的二分法。
(有收获的话求个赞…)
代码
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
vector<int> res(2,-1);
if(nums.size()==0) return res;
if(nums.size() == 1) {
if(nums[0] == target){
res = {0,0};
return res;
}else{
return res;
}
}
int left = 0, right = nums.size()-1;
if(nums[left]>target || nums[right]<target) return res;//排除不存在的情况
// 以上是对能想到的特殊情况进行讨论,多讨论一点边界情况总是不坏的。
while(left<right){
if(nums[left] == target){
res[0] = left;
res[1] = getRight(nums,left+1,right,target);
return res;
}
if(nums[right] == target){
res[1] = right;
res[0] = getLeft(nums,left,right-1,target);
return res;
}
// 二分代码只有下面5行,其余全部都是一些判断,相当于已经找到了突破口
int mid = left+ (right-left)/2;
if(nums[mid]<target){
left = mid + 1;
}else if(nums[mid]>target){
right = mid;
}else{
res[0] = getLeft(nums,left,mid-1,target);
res[1] = getRight(nums,mid+1,right,target);
return res;
}
}
if(left==right && nums[left] == target){
res[0] = res[1] = left;
return res;
}else{
res[0] = res[1] = -1;
return res;
}
}
int getLeft(vector<int>& nums, int left, int right, int target){
// 走到这一步,left和right之间的数都是小于等于target的
if(target>nums[right]) return right+1;
if(left<right){//nums[right] == target,nums[left]<target
int mid = left+ (right-left+1)/2;
if(nums[mid]==target){
return getLeft(nums,left,mid-1,target);// 很自然的写成了递归形式的二分
}else{ // nums[mid]<target
return getLeft(nums,mid,right,target);
}
}else {
return left;
}
}
int getRight(vector<int>& nums, int left, int right, int target){
// 走到这一步,left和right之间的数都是小于等于target的
if(nums[left]>target) return left-1;
if(left<right){
int mid = left+ (right-left)/2;
if(nums[mid] == target){
return getRight(nums,mid+1,right,target);
}else{
return getRight(nums,left,mid,target);
}
}else{
return left;
}
}
};