书上写的是递归法,个人更喜欢循环写二分查找。
这道题给的有序数组第一思路是二分查找k,然后向两侧扫描找到起点终点,但这样时间复杂度是O (n).
巧妙地思路是两次二分查找,第一次找first第一次出现的下标,只需要把二分查找条件变一下就好了,第二次找last,最后返回last - first +1.
这里的陷阱是如果数组里没有这个数,就会返回1,把first设为-1如果没找到返回0.
int GetNumberOfK(vector<int> data, int k) {
int first = -1; //如果没找到还是-1
int last = 0;
int left = 0;
int right = data.size() - 1;
//找first
while (left <= right) {
int mid = left + ((right - left) >> 1);
if (data[mid] == k) {
if (mid > 0 && data[mid - 1] == k) {
right = mid - 1;
}
else {
first = mid;
break;
}
}
else if (data[mid] < k) {
left = mid + 1;
}
else {
right = mid - 1;
}
}
//找last
left = 0;
right = data.size() - 1;
while (left <= right) {
int mid = left + ((right - left) >> 1);
if (data[mid] == k) {
if ((mid < data.size()-1) && data[mid + 1] == k) {
left = mid + 1;
}
else {
last = mid;
break;
}
}
else if (data[mid] < k) {
left = mid + 1;
}
else {
right = mid - 1;
}
}
return first== -1 ? 0 : last - first + 1;
}