1、问题描述
求一个数出现在排序数组中的次数。
2、解题思路
- (1)功能测试:输入排序数组为升序数组;输入排序数组为降序数组;输入排序数组中的元素全部相同;输入的数字在排序数组中不存在。
- (2)边界值测试:排序数组中只有一个元素;
- (3)特殊输入测试:排序数组为空;
- 思路1:由于是有序数组,如果一个数在数组中出现多次,那么这些相同的数的位置一定相邻。在有序的数组中查找某个数可以采用二分查找,二分查找的思想是,每次将要查询数 k k k和数组中间位置的数对比,如果查询数k大于中间位置的数,那么在数组的右半部分查找,否则,在数组的左半部分查找。二分查找只负责找到一个等于查询数的数(或找不到),而至于查询数在在数组中出现的次数则无能为力。
- 实际上,要想知道查询数
k
k
k出现的次数,只需在数组中找到第一个查询数和最后一个查询数即可。因此,我们可以对二分查找算法稍加修改,实现查询数在数组中出现次数的求解。具体步骤如下:
<1>查找第一个k
先将 k k k和数组中间的数 m m m进行比较,如果 k < m k<m k<m,则在m的左边查找;如果 k > m k>m k>m,则在m的右边查找;如果 k = = m k==m k==m,则看m前面的一个数是否等于 k k k,如果相等,则说明m不是第一个 k k k,第一个k在m的左边,继续在m的左边查找。
<2>查找最后一个k
先将 k k k和数组中间的数 m m m进行比较,如果 k < m k<m k<m,则在m的左边查找;如果 k > m k>m k>m,则在m的右边查找;如果 k = = m k==m k==m,则看m后面的一个数是否等于 k k k,如果相等,则说明m不是最后一个 k k k,最后一个k在m的右边,继续在m的右边查找。 - 这种方法使用了两次二分查找算法来查找某个合乎要求的数。所以最终的时间复杂度为 O ( l o g n ) O(logn) O(logn)。
3、代码实现
public class Solution {
public int GetNumberOfK(int [] array , int k) {
int number = 0;
if (array == null || array.length == 0){
number = 0;
}
else if(array.length == 1){
if(array[0] == k){
number = 1;
}
}
else {
int ld = GetFirstK(array,k,0,array.length - 1);
int rd = GetLastK(array,k,0,array.length - 1);
if(ld != -1 && rd != -1){
number = rd - ld + 1;
}
}
return number;
}
public int GetFirstK(int [] array, int k, int left, int right){
int index = -1;
if (left <= right) {
int middle = (right + left) >> 1;
if (k < array[middle]) {
index = GetFirstK(array, k, left, middle -1);
}
else if(k > array[middle]){
index = GetFirstK(array, k, middle + 1,right);
}
else {
if (middle != left){
if (array[middle - 1] == k) {
index = GetFirstK(array, k, left, middle - 1);
} else {
index = middle;
}
}
else {
index = middle;
}
}
}
return index;
}
public int GetLastK(int [] array, int k, int left, int right){
int index = -1;
if (left <= right) {
int middle = (right + left) >> 1;
if (k < array[middle]) {
index = GetLastK(array, k, left, middle -1);
}
else if(k > array[middle]){
index = GetLastK(array, k, middle + 1,right);
}
else {
if (middle != right){
if (array[middle + 1] == k) {
index = GetLastK(array, k, middle + 1, right);
} else {
index = middle;
}
}
else {
index = middle;
}
}
}
return index;
}
}