34.在排序数组中查找元素的第一个和最后一个位置
给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
你的算法时间复杂度必须是 O(log n) 级别。
如果数组中不存在目标值,返回 [-1, -1]。
示例 1: |
---|
输入: nums = [5,7,7,8,8,10], target = 8 输出: [3,4] |
示例 2: |
---|
输入: nums = [5,7,7,8,8,10], target = 6 输出: [-1,-1] |
我的解法:
采用一次二分查找,找出nums[mid]=target的mid, 然后分别向左向右查找第一次以及最后一次出现的位置。
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
vector<int>res(2, -1);
int left = 0, right = nums.size()-1, mid;
while(left<=right){
mid = left + (right-left)/2;
if(nums[mid] > target) right = mid-1;
else if(nums[mid] < target) left = mid+1;
else{
while(mid != 0 && nums[mid] == nums[mid-1])
mid--;
res[0] = mid;
while(mid != nums.size()-1 && nums[mid] == nums[mid+1])
mid ++;
res[1] = mid;
break;
}
}
return res;
}
};
更优解,利用二分思想先找其左边界,再找其右边界即可,注意找左边界的时候,由右侧逼近;找右边界的时候,由左侧逼近,即可。
【这个左右逼近一直没太搞明白,以后慢慢看】
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
vector<int> res(2,-1);
if(nums.empty()) return res;
int n=nums.size(),l=0,r=n-1;
while(l<r){
int m=l+(r-l)/2;
if(nums[m]>=target) r=m;
else l=m+1;
}
if(nums[l]!=target) return res;
res[0]=l;
r=n;
while(l<r){
int m=l+(r-l)/2;
if(nums[m]<=target) l=m+1;
else r=m;
}
res[1]=l-1;
return res;
}
};
Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.