题目描述
统计⼀个数字在升序数组中出现的次数。
示例1 输⼊:[1,2,3,3,3,3,4,5],3 返回值:4
思路及解答
线性遍历
顺序遍历数组,遇到目标值就计数
时间复杂度:O(n),最坏情况下需要遍历整个数组
空间复杂度:O(1),只使用常数级别额外空间
二分查找+左右扫描法
先使用二分查找定位到目标值,然后向两边扩展统计。
由于数组是有序的,可以明显看到是二分法。
第1步是找出数值为 k 的数的索引: 假设数组为 nums[],⼀开始的左边索引为 left = 0,右边界索引为 right = nums.length-1
将数组分成两部分,中间的数为 nums[mid] 。第1部分为 [left,mid] ,第2部分为[mid+1,right]。
如果 nums[mid]>k ,则说明 k 只可能存在前半部分中,对前半部分执⾏操作1。
如果 nums[mid]<k ,则说明 k 只可能存在后半部分中,对后半部分执⾏操作1。
如果 nums[mid]=k ,直接返回当前索引 mid 。
如果 left > right ,说明 k 不存在,则返回 -1 。
找到索引之后,往两边扩展,同时统计k的个数,直到元素不等于 k 的时候停⽌。

时间复杂度:O(log n + k),其中k是目标值出现次数。当目标值出现次数较少时效率接近O(log n),但最坏情况(全部是目标值)退化为O(n)
空间复杂度:O(1)
双二分查找法(推荐)
分别使用二分查找找到目标值的起始和结束位置,计算区间长度,这是最优解法。
时间复杂度:O(log n),执行两次二分查找
空间复杂度:O(1),只使用常数空间
k±0.5边界查找法
一种巧妙的解法,通过查找目标值边界的插入位置来计算出现次数。
由于数组元素都是整数,k-0.5和k+0.5正好是目标值范围的边界,它们的插入位置差值就是目标值出现次数。
时间复杂度:O(log n),两次二分查找
空间复杂度:O(1)