题目
给定一个按照升序排列的整数数组 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]
思路
- O(logn)需要用二分法。
- 用二分法分别找最左边的target和最右边的target。
- 如果左右索引为left、right。
- 找最左边的target
- 循环条件 while (left < righ),当left = right的时候循环停止。
- 当target < nums[mid]时,使right = mid。
- 当target = nums[mid]时, 使right = mid。
- 当target > nums[mid]时,使left = mid + 1。
- 偶数的时候,中间有两个数,让mid等于靠左的那个。防止死循环。
- 找最右边的target。
- 循环条件 while (left < righ),当left = right的时候循环停止。
- 当target < nums[mid]时,使right = mid - 1。
- 当target = nums[mid]时, 使;left = mid。
- 当target > nums[mid]时,使left = mid。
- 偶数的时候,中间有两个数,让mid等于靠右的那个。防止死循环。
代码
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
if ( nums.size() == 0 ) return { -1, -1 };
int firstTarget = getFirstTarget( nums, target );
if ( firstTarget == -1 ) return { -1, -1 };
int lastTarget = getLastTarget( nums, target );
return { firstTarget, lastTarget};
}
int getFirstTarget( vector<int>& nums, int target ) {
int res = -1;
int left = 0, right = nums.size() - 1;
// 找到左边的target
while ( left < right ) {
int mid = ( left + right ) >> 1;
if ( nums[mid] >= target )
right = mid;
else
left = mid + 1;
}
if ( nums[right] == target )
res = right;
return res;
}
int getLastTarget( vector<int>& nums, int target ) {
int left = 0, right = nums.size() - 1;
// 找到右边的target
while ( left < right ) {
int mid = ( left + right + 1 ) >> 1;
if ( nums[mid] <= target )
left = mid;
else
right = mid - 1;
}
return left;
}
};