1.本题知识点
二分查找
2. 题目描述
统计一个数字在排序数组中出现的次数。
3. 思路
一搬情况下,排序数组中的查找都可以通过二分查找来解决。
① 通过二分查找查找k,分别找到第一次出现的位置和最后一次出现的索引位置。
② 通过k出现的第一和最后的位置直接计算出现次数即可,last - first +1。
③ 二分值mid的三种情况:
- mid > k ,k出现在左子树,只在左子树中查找
- mid < k ,k出现在右子树,只在右子树中查找
- mid = k, 判断k是不是一个k或最后一个k
- 若k的前一个元素还是等于k,则在左子树中继续二分查找
- 同理,k的后一个元素还是等于k,则在右子树中继续二分查找
Java版本:
package com.algorithm.array;
public class NumCount {
public static void main(String[] args) {
int [] arr = {1,3,5,5,5,8,11,14,14,15};
int count = GetNumberOfK(arr, 14);
System.out.println(count);
}
private static int GetNumberOfK(int [] array, int k) {
if(array == null && array.length == 0) return -1;
int first = getFirstK(array, 0, array.length-1, k);
int last = getLastK(array, 0, array.length-1, k);
if(first > -1 && last > -1){
return last - first + 1;
}
return 0;
}
static int getFirstK(int [] arr,int left ,int right,int k){
if(arr == null && arr.length == 0){
return -1;
}
while(left <= right){
int midIndex = (left + right) >> 1;
if(arr[midIndex] > k){
right = midIndex - 1;
}
else if(arr[midIndex] < k){
left = midIndex + 1;
}
else{
if((midIndex > 0 && arr[midIndex -1] != k) || midIndex == 0){
return midIndex;
}
else{
right = midIndex - 1;
}
}
}
return -1;
}
static int getLastK(int [] arr,int left ,int right,int k){
if(arr == null && arr.length == 0){
return -1;
}
while(left <= right){
int midIndex = (left + right) >> 1;
if(arr[midIndex] > k){
right = midIndex - 1;
}
else if(arr[midIndex] < k){
left = midIndex + 1;
}
else{
if((midIndex < arr.length -1 && arr[midIndex +1] != k) || midIndex == arr.length -1){
return midIndex;
}
else{
left = midIndex + 1;
}
}
}
return -1;
}
}