题目
统计一个数字在排序数组中出现的次数。例如输入排序数组{1, 2, 3, 3,3, 3, 4, 5}和数字3,由于3在这个数组中出现了4次,因此输出4。
解题思路
首先分析如何用二分查找算法在数组中找到第一个k。二分查找算法总是先拿数组中间的数字和k作比较。如果中间的数字比k大,那么k只有可能出现在数组的前半段,下一轮我们只在数组的前半段查找就可以了。如果中间的数字比k小,那么k只有可能出现在数组的后半段,下一轮我们只在数组的后半段查找就可以了。
如果中间的数字和k相等呢?我们先判断这个数字是不是第一个k。
如果位于中间数字的前面一个数字不是k,此时中间的数字刚好就是第一个k。
如果中间数字的前面一个数字也是k,也就是说第一个k肯定在数组的前半段,下一轮我们仍然需要在数组的前半段查找。
测试用例
1.功能测试(数字出现次数为0、1、2等)
2.边界值测试(数组只有一个数字,查找数字为第一个或者最后一个)
2.特殊测试(null)
代码
package mySword;
//题目:统计一个数字在排序数组中出现的次数。
//例如输入排序数组{1, 2, 3, 3, 3, 3, 4, 5}和数字3,由于3在这个数组中出现了4次,因此输出4。
public class getNumberOfK {
public static int getNumberOfK(int[] arr, int k){
if(arr == null || arr.length == 0){
return -1;
}
int indexOfFirstK = getFirstK(arr, 0 , arr.length-1, k);
int indexOfLastK = getLastK(arr, 0, arr.length-1, k);
return indexOfLastK - indexOfFirstK + 1;
}
//GetFirstK:找到数组中第一个k的下标。如果数组中不存在k,返回-1
public static int getFirstK(int[] arr, int start, int end, int k){
if(start > end){
return -1;
}
int mid = start + (end - start)/2;
if(arr[mid] == k){
if(mid == 0 || arr[mid-1] != k){
return mid;
}else{
end = mid - 1;
}
}else if(arr[mid] < k){
start = mid+1;
}else{
end = mid-1;
}
return getFirstK(arr, start, end, k);
}
//GetLastK:找到数组中最后一个k的下标。如果数组中不存在k,返回-1
public static int getLastK(int[] arr, int start, int end, int k){
while(start > end){
return -1;
}
int mid = start + (end - start)/2;
if(arr[mid] == k){
if(mid == arr.length-1 || arr[mid+1] != k){
return mid;
}else{
start = mid + 1;
}
}else if(arr[mid] < k){
start = mid + 1;
}else{
end = mid - 1;
}
return getLastK(arr, start, end, k);
}
public static void main(String[] args) {
int[] arr = {1, 2, 3, 3, 3, 3, 4, 5};
System.out.println(getNumberOfK(arr, 3));
}
}