思路:
- 二分查找,找到后分别向左向右遍历有多少重复的,然后记录左右端点即可,但是这样在某些情况下复杂度为(O(n)),比如{8,8,8,8,8,8,8,8,8}。竟然过了。。。
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
int mid,lo = 0, hi = nums.size()-1;
if(nums.size() == 0) return {-1,-1};
int k = 0;
std::vector<int> v;
while(lo <= hi){
mid = (lo + hi) / 2;
cout << "ho " << hi << " lo " << lo << endl;
cout << "mid " << mid << " nums[mid] " << nums[mid] << endl;
if(nums[mid] == target){
cout << target << endl;
for(int i = mid-1; i >= 0; i--){
if(nums[i] == target) k++;
}
int left = mid - k;
k = 0;
for(int i = mid+1; i < nums.size(); i++){
if(nums[i] == target) k++;
}
int right = mid + k;
v.push_back(left);
v.push_back(right);
return v;
}
else if(nums[mid] < target) lo = mid+1;
else hi = mid-1;
}
return {-1,-1};
}
};
- 用二分分别查找左端点和右端点,每次的复杂度都为(O(log(n)))。注意:1.要考虑是否找到;2.要考虑有没有越界(wa了好几次。。)
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
int mid,lo = 0, hi = nums.size()-1;
int k = 0;
std::vector<int> v = {-1,-1};
if(nums.size() == 0) return v;
while(lo <= hi){
mid = (lo + hi) / 2;
if(nums[mid] < target) lo = mid+1;
else hi = mid-1;
}
int left = lo;
if(left < nums.size() && nums[left] == target) v[0] = left; //注意
lo = 0,hi = nums.size()-1;
while(lo <= hi){
mid = (lo + hi) / 2;
if(nums[mid] > target) hi = mid-1;
else lo = mid + 1;
}
int right = hi;
if(right >= 0 && nums[right] == target) v[1] = right; //注意
return v;
}
};
总结:
- 每次二分要判断是否找到
- 测试程序要考虑到[],[a]两种特殊情况