题目:
统计一个数字在排序数组中出现的次数。
思路:
利用二分查找法,分别查找数字在顺序数组中第一次出现的坐标和最后一次出现的坐标。
1、第一次出现的坐标:
先将数组中间数字与k进行比较,
(1)若中间数字等于k,如果中间数字的前一位不等于k,则返回中间数字的坐标;如果中间数字的前一位等于k,则第一个k肯定出现在数组的前半段,下一轮在数组的前半段进行查找。
(2)若中间数字大于k,则k只能出现在数组的前半段。下一轮在数组的前半段进行查找。
(3)若中间数字小于k,则k只能出现在数组的后半段。下一轮在数组的后半段进行查找。
2、最后一次出现的坐标
先将数组中间数字与k进行比较,
(1)若中间数字等于k,如果中间数字的后一位不等于k,则返回中间数字的坐标;如果中间数字的后一位等于k,则第一个k肯定出现在数组的后半段,下一轮在数组的后半段进行查找。
(2)若中间数字大于k,则k只能出现在数组的前半段。下一轮在数组的前半段进行查找。
(3)若中间数字小于k,则k只能出现在数组的后半段。下一轮在数组的后半段进行查找。
程序:
public class subject37 {
public static int GetNumberOfK(int[] array, int k) {
if(array.length == 0 || array == null) {
return 0;
}
int first = getFirst(array, k, 0, array.length - 1);
int last = getLast(array, k, 0, array.length - 1);
if(first > -1 && last > -1) {//判断数组中是否包含k
return last - first + 1;
}
return 0;
}
public static int getFirst(int[] array, int k, int start, int end) {
//找数字在排序数组中第一次出现的坐标
if(start > end || array.length == 0 || array == null) {
return -1;
}
int midIndex = start + (end - start) / 2;
int midData = array[midIndex];
if(midData == k) {//先判断中间数字是不是等于k
if(midIndex > 0 && array[midIndex - 1] != k || midIndex == 0) {
//判断中间数字的前一个数是不是等于k
return midIndex;
}else {
end = midIndex - 1;
}
}else if(midData > k) {//若中间数字的值大于k,下一次从start ~ midIndex-1范围内查找
end = midIndex - 1;
}else {
start = midIndex + 1;//若中间数字的值大于k,下一次从midIndex+1 ~ end范围内查找
}
return getFirst(array, k, start, end);
}
public static int getLast(int[] array, int k, int start, int end) {
//找数字在排序数组中最后一次出现的坐标
if(start > end || array.length == 0 || array == null) {
return -1;
}
int midIndex = start + (end - start) / 2;
int midData = array[midIndex];
if(midData == k) {
if(midIndex < array.length - 1 && array[midIndex + 1] != k || midIndex == array.length - 1) {
return midIndex;
}else {
start = midIndex + 1;
}
}else if(midIndex > k) {
end = midIndex - 1;
}else {
start = midIndex + 1;
}
return getLast(array, k, start, end);
}
public static void main(String args[]) {
int[] array = new int[] {1,3,3,3,3,4,5};
System.out.println(GetNumberOfK(array,2));
}
}