一、 题目
给出一个已经排好序的数组和一个数字,找出在这个数字在数组中的范围。
例如:[5,7,7,8,8,10]和8
返回:[3,4]
二、 分析
题目很基础,就是找出等值的数字的开始和结束索引,上去就遍历当第一次遇到等值时记录下左索引,最后一次遇到记录下右索引也不会超时。如下:
//遍历法
class Solution {
public:
vector<int> searchRange(int A[], int n, int target) {
vector<int> res;
int k = 0;
int min = -1, max = -1;
while(k <= n-1){
if(A[k] == target && min == -1){
min = k;
max = k;
}
else if(A[k] == target && min != -1){
max = k;
}
k++;
}
res.push_back(min);
res.push_back(max);
return res;
}
};
然后总觉得这样是不是没挑战力呢?那就优化吧,二分查找,找出其中一个数字,然后向左和向右找出边界即可(看到网上说的使用两次或三次二分,我感觉完全没有必要,找到一个等值接下来直接找边界就行了)。
class Solution {
public:
vector<int> searchRange(int A[], int n, int target) {
vector<int> res;
int min = -1, max = -1;
int left = 0, right = n-1;
int value = -1;
while(left <= right){
int mid = (left + right)/2;
if(A[mid] < target){
left = mid + 1;
}else if(A[mid] > target){
right = mid - 1;
}else if(A[mid] == target){
value = mid;
break;
}
}
if(value != -1){
for(int i = value; i < n; i++)
if(A[i] == target)
max = i;
else
break;
for(int j = value; j >= 0; j--)
if(A[j] == target)
min = j;
else
break;
}
res.push_back(min);
res.push_back(max);
return res;
}
};