Description
Given an array of integers sorted in ascending order, find the starting and ending position of a given target value.
Your algorithm’s runtime complexity must be in the order of O(log n).
If the target is not found in the array, return [-1, -1].
For example,
Given [5, 7, 7, 8, 8, 10] and target value 8,
return [3, 4].
分析:
这是leetcode上的一道利用二分法求解的题目,属于medium难度。关键的难点就在于题目限制了时间复杂度为O(logn),也就是说查找的时候必须每次都缩小一半的范围,这也是二分法的精髓所在。定位成功后,还要前后遍历搜素等值的位置,因为目标值可能出现了不止一次,最后靶目标值出现位置的头尾记录下来,用vector返回即可。
具体做法:
- step1:构造一个find()函数,每次去搜索范围的中间值与target进行比较,若相等则返回此时的position,若target比中间值小,则在前一半继续搜索,若target比中间值大,则在后一半继续搜索,直到找到position或范围只剩下一个元素。
step2:将得到的值与target进行比较,若不相等,则返回[-1, -1];若相等,则分别向前向后遍历nums数组,将所有与target值相等的位置找出来,最后返回头和尾。
注:一个细节问题:需要先判断读入的数组是否为空,否则会出现越界的错误!
代码
#include <iostream>
#include <vector>
using namespace std;
int find(vector<int>& nums, int s, int e, int target){
if (s < e){
int mid = (s + e) / 2;
/*分别讨论相等、比target小,比target大三种情况*/
if (target == nums[mid]) return mid;
else if (target < nums[mid]) return find(nums, s, mid - 1, target);
else return find(nums, mid + 1, e, target);
}
/*只剩一个元素的时候返回*/
else return s;
}
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
vector<int> v;
/*先判断数组是否为空,防止越界错误!*/
if (nums.empty()){
v.push_back(-1);
v.push_back(-1);
return v;
}
int pos = find(nums, 0, nums.size() - 1, target);
/*如果没有找到target,则返回[1, 1]*/
if (nums[pos] != target){
v.push_back(-1);
v.push_back(-1);
return v;
}
/*找到目标值所在区域的头尾并返回*/
int pos_big = pos, pos_small = pos;
while (pos_small > 0 && nums[pos_small - 1] == nums[pos]) pos_small--;
while (pos_big < nums.size() - 1 && nums[pos_big + 1] == nums[pos]) pos_big++;
v.push_back(pos_small);
v.push_back(pos_big);
return v;
}
};