https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/
给定一个按照升序排列的整数数组 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]
方法一:线性查找
设置两个指针 i = 0, j = nums.size(), 分别从左右两端向中间移动,一旦指向元素的值为 target, 则停止。
该方法运行时间为 O(n), 不满足题意。
方法二:多次二分查找
由于需要求解区间,因此朴素的二分查找并不满足要求。
将二分查找多次使用,每次均在指定区间内寻找 target 元素。
若区间的端点值并不满足要求(即 target 一定不存在于该区间),则忽略该区间。例如: [left, …, middle] 中,若 nums[middle] < target, 则忽略该区间;[middle + 1, …, right] 中,若 nums[middle + 1] > target, 则忽略该区间。
若在区间中 middle 位置可以找到 target, 则比较 middle 与当前记录的结果区间的两侧比较,之后继续递归。
代码:
class Solution {
public:
vector<int> res{-1};
void search( const vector<int>& nums, const int& target, int left, int right){
// cout<<" left = "<while ( left < right){
int middle = left + ( right - left)/2;
// cout<<" left = "<if ( nums[middle] < target)
left = middle + 1;
else if( nums[middle] > target)
right = middle - 1;
//以上两种情况可以将一般的数据忽略
else if( nums[middle] == target){
if( middle > res[0]) //若大于最左侧下标
res[0] = middle;
if( middle < res[1]) //若小于最右侧下标
res[1] = middle;
search( nums, target, middle + 1, right);
search( nums, target, left, middle - 1);
return ;
}
}
if( left < nums.size() && nums[left] == target){
if( left > res[0]) //若大于最左侧下标
res[0] = left;
if( left < res[1]) //若小于最右侧下标
res[1] = left;
}
return ;
}
vector<int> searchRange(vector<int>& nums, int target) {
res.push_back( nums.size());
search( nums, target, 0, nums.size() - 1);
if( res[0] == -1)
return {-1,-1};
swap( res[0], res[1]);
return res;
}
};