题目描述
统计一个数字在升序数组中出现的次数。
示例
输入:[1,2,3,3,3,3,4,5],3
返回值:4
算法思路
这题就是二分查找算法的应用,请参考这边文章
二分查找模板
这道题的算法思路:
- 查找出目标数字在数组中出现的左侧边界
- 查找出目标数字在数组中出现的右侧边界
- 然后右侧边界-左侧边界+1就是目标数字在升序数组中出现的次数
代码实现
public class Solution {
public int GetNumberOfK(int [] nums , int target) {
int left = binarySearch_left(nums,target);
//左侧边界没有。说明数组中没有这个数组,直接返回0
if(left==-1){
return 0;
}
int right = binarySearch_right(nums,target);
//右侧边界没有。说明数组中只出现了一次,直接返回1
if(right==-1){
return 1;
}
//左右两侧都找到
return right-left+1;
}
/**
* 查找左侧边界
*
* @param nums
* @return
*/
private static int binarySearch_left(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;//注意
//left=right+1结束循环
while (left <= right) {
int mid = left + ((right - left) >> 1);
if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid - 1;
} else {
right = mid - 1;//向左收缩边界
}
}
//条件判断
if (left >= nums.length || nums[left] != target) {
return -1;
}
//这里返回值是根据num[mid]==target来返回的,此时right=mid-1
//相当于mid = right+1
//而结束条件right+1=left
//相当于mid = left
//所以返回left或者right+1都可以
return left;
}
/**
* 查找右侧边界
*
* @param nums
* @return
*/
private static int binarySearch_right(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;//注意
while (left <= right) {
int mid = left + ((right - left) >> 1);
if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid - 1;
} else {
left = mid + 1;//向右侧收缩边界
}
}
//条件判断
if (right < 0 || nums[right] != target) {
return -1;
}
//这里返回值是根据num[mid]==target来返回的,此时left=mid+1
//相当于mid = left-1
//而结束条件right+1=left,right-left-1
//相当于mid=right
//所以返回left-1或者right都可以
return right;
}
}