解法:二分法
思想:
二分查找通常用于查找单个数,所以用在此题需要改变一下。
定义一个函数,返回target右边的数的索引,结果可以通过find(target) - find(target - 1)
得到
过程:
●初始化:在区间[0, nums.size() - 1]中查找,令left和right为左右边界
●定义左右区间:左区间小于等于target, 右区间大于target
●循环二分:
1.计算中点mid
2.如果nums[mid] <= target,说明右子数组的首位元素一定在[mid + 1, right]中
3.如果nums[mid] > target,说明左子数组的末位元素一定在[left, mid - 1]
●返回值:
最后left和right分别指向 右子首位元素 和 左子末位元素,因此返回left
复杂度:
●时间 :O(logN),利用两次二分查找
●空间:O(1)
代码:
class Solution {
public:
int search(vector<int>& nums, int target) {
return findNumRight(nums, target) - findNumRight(nums, target - 1);
}
//寻找target右边首位数的索引
int findNumRight(vector<int> &nums, int target){
if(nums.empty())
return 0;
int left = 0, right = nums.size() - 1;
while(left <= right){
int mid = left + (right - left) / 2;
//因为是从右边插入,所以肯定在mid右边,所以mid + 1
if(nums[mid] <= target)
left = mid + 1;
//也需要减一
else
right = mid - 1;
}
//最后left肯定为right + 1,要返回的是右边的数的索引,所以返回left
return left;
}
};