统计一个数字在排序数组中出现的次数。
在排序数组中查找一个数,这明显就需要利用二分法。不过现在需要在数组中找某个数出现的次数,那么我们就需要找到这个数字在数组中第一次出现的位置,以及最后一次出现的位置,将这两个下标一减再加上1就是我们需要的结果。
找第一次出现的位置时,我们利用二分法找到了目标值,它的下标为i,此时还不能停止寻找,我们得判断一下 i - 1 位置上的数是否也是目标值,如果是,那么就继续二分的过程,如果不是,那么我们就找到了这个第一次出现的位置。
找最后一次出现的位置也是同理,找到目标值后,再判断一下i + 1位置的数是否也是目标值,然后决定是否继续二分。
代码如下:
import org.junit.Test;
public class Solution1 {
public int findFirst(int[] array, int target, int start, int end) {
if (start > end) {
return -1;
}
int mid = (start + end) / 2;
int num = array[mid];
if (num == target) {
if ((mid > 0 && array[mid - 1] != target) || mid == 0) {
return mid;
} else {
end = mid - 1;
}
} else if (num > target) {
end = mid - 1;
} else {
start = mid + 1;
}
return findFirst(array, target, start, end);
}
// 这里也是给自己一个警示吧,以后写参数列表的时候,越重要的参数,越要往前放,这样出错的概率机会低
public int findLast(int[] array, int target, int start, int end, int length) {
if (start > end) {
return -1;
}
int mid = (start + end) / 2;
int num = array[mid];
if (num == target) {
if ((mid < length - 1 && array[mid + 1] != target) || mid == length - 1) {
return mid;
} else {
start = mid + 1;
}
} else if (num < target) {
start = mid + 1;
} else {
end = mid - 1;
}
return findLast(array, target, start, end, length);
}
public int GetNumberOfK(int[] array, int k) {
if (array == null) {
return -1;
}
int len = array.length;
int first = findFirst(array, k, 0, len - 1);
// start 和 end 是二分的时候的数组下标,取值范围就是(0, len - 1);而length是数组的长度,范围是(1, len)
int last = findLast(array, k, 0, len - 1, len);
int result = 0;
// 考虑目标不在数组中的情况
if (first != -1 && last != -1) {
result = last - first + 1;
}
return result;
}
@Test
public void test() {
int[] arr = {1, 1, 2, 2, 3, 5, 5, 9, 9};
int k = 9;
int result = GetNumberOfK(arr, k);
System.out.println(result);
}
}