题目
统计一个数字在排序数组中出现的次数。
解析
如何做到举一反三呢?这是个值得思考的问题,漠然忍受命运暴虐的毒箭,或是挺身反抗人世无涯的苦难,通过斗争把他扫清…跑题跑题啦!!
题目中出现 排序数组 时,我们应该直觉反应,可以使用二分查找算法。
因为是排序数组,所以我们可以找到出现指定数字的第一个位置和最后一个位置,从而来确定该数在数组中出现的次数。
如何找到第一次出现该数字的位置呢?
我们用二分查找,如果中间的数值是指定数,那么就判断前一个数是否是该数,若不是,该位置就是该数第一次出现的位置,此时还有一个特殊情况,若此时midIndex == 0 时,那么就不需要进行前一个位置的判断,0位置就是第一次出现的位置;如果中间位置的数值大于该数,说明该数出现的第一个位置在前半部分;反之,如果中间位置的数值小于该数,则说明该出第一次出现的位置在后半部分。
同理,我们可以得出该数的最后一次出现的位置。
至此,我们就能求出该数在这个排序数组中出现的次数。
这个算法的时间复杂度是 O(logn)。
Java 代码
public class Solution {
public int GetNumberOfK(int [] array , int k) {
int number = 0;
if (array != null && array.length > 0) {
int first = GetFirstOfK(array, 0, array.length - 1, k);
int last = GetLastOfK(array, 0, array.length - 1, k);
if (first > -1 && last > -1)
number = last - first + 1;
}
return number;
}
private int GetFirstOfK(int [] array, int start, int end, int k) {
if (start > end)
return -1;
int midindex = (start + end) / 2;
int midIndexData = array[midindex];
if (midIndexData == k) {
if ((midindex > 0 && array[midindex - 1] != k) || midindex == 0)
return midindex;
else
end = midindex - 1;
} else if (midIndexData > k)
end = midindex - 1;
else
start = midindex + 1;
return GetFirstOfK(array,start,end,k);
}
private int GetLastOfK(int [] array, int start, int end, int k) {
if (start > end)
return -1;
int midIndex = (start + end) / 2;
int midIndexData = array[midIndex];
if (midIndexData == k) {
if ((midIndex < array.length - 1 && array[midIndex + 1] != k) || midIndex == array.length - 1)
return midIndex;
else
start = midIndex + 1;
} else if (midIndexData > k)
end = midIndex - 1;
else
start = midIndex + 1;
return GetLastOfK(array, start, end, k);
}
}