题目描述
统计一个数字在升序数组中出现的次数。
示例1
输入
[1,2,3,3,3,3,4,5], 3
返回值
4
看到数组是有序的,并且是查找,应该想到用二分法,最简单的方法是用二分法找到该数,然后以它为中心向左右两边搜索计数
public class Solution {
public int GetNumberOfK(int[] array, int k) {
// 二分查找
int low = 0, high = array.length - 1, middle;
int count = 0;
while (low <= high) {
middle = (low + high) / 2;
if (k > array[middle])
low = middle + 1;
else if (k < array[middle])
high = middle - 1;
else {
// find k
int i = middle;
while (i >= 0 && array[i] == k) {
count++;
i--;
}
i = middle + 1;
while (i < array.length && array[i] == k) {
count++;
i++;
}
break;
}
}
return count;
}
}
优化方法是利用二分法找到k第一次出现和最后一次出现的位置,相减即可得到k出现的次数。为了得到第一次出现的位置和最后一次出现的位置,需要稍微改写二分法。
第一次出现的位置
当array[middle] == k 时,令high = middle - 1,继续往前找第一个出现的位置,最后返回low
int low = 0, high = array.length - 1, middle = (low + high) / 2;
// get index of the first k.
while (low <= high) {
middle = (low + high) / 2;
if (k > array[middle]) {
low = middle + 1;
}
// array[middle] == k 时,令high = middle - 1,继续往前找第一个出现的位置
else {
high = middle - 1;
}
}
return low;
最后一次出现的位置
当array[middle] == k 时,令low = middle + 1,继续往后找最后一个出现的位置,最后返回high
int low = 0, high = array.length - 1, middle = (low + high) / 2;
// get index of the last k.
while (low <= high) {
middle = (low + high) / 2;
// array[middle] == k 时,令low = middle + 1,继续往后找最后一个出现的位置
if (k >= array[middle]) {
low = middle + 1;
} else {
high = middle - 1;
}
}
return high;
总代码
public class Solution {
public int GetNumberOfK(int[] array, int k) {
// 二分查找
int first = getK(array, k, true);
int last = getK(array, k, false);
System.out.println(first + " " + last);
return last - first + 1;
}
public int getK(int[] array, int k, boolean first) {
int low = 0, high = array.length - 1, middle = (low + high) / 2;
if (first) {
// get index of the first k.
while (low <= high) {
middle = (low + high) / 2;
if (k > array[middle]) {
low = middle + 1;
}
// array[middle] == k 时,令high = middle - 1,继续往前找第一个出现的位置
else {
high = middle - 1;
}
}
return low;
} else {
// get index of the last k.
while (low <= high) {
middle = (low + high) / 2;
// array[middle] == k 时,令low = middle + 1,继续往后找最后一个出现的位置
if (k >= array[middle]) {
low = middle + 1;
} else {
high = middle - 1;
}
}
return high;
}
}
public static void main(String[] args) {
int[] num = {
1, 2, 3, 3, 3, 3, 4, 5};
new Solution().GetNumberOfK(num, 6);
}
}