本题为剑指offer面试题38
牛客网测试地址:https://www.nowcoder.com/questionTerminal/70610bf967994b22bb1c26f9ae901fa2
- 时间限制:1秒空间限制:32768K
统计一个数字在排序数组中出现的次数。
Java代码
package go.jacob.day512;
public class Demo1 {
/*
* 方法一:用二分查找在数组中找到k所对应的下标(如果不存在返回-1),然后分别向前向后遍历,统计k出现的次数 该方法不是最优
*/
public int GetNumberOfK_1(int[] array, int k) {
// 考虑无效输入
if (array == null)
return -1;
int kIndex = binaryFind(array, 0, array.length - 1, k);
int num = 0;
// 易错点1:考虑数组中不存在要查找的数字
if (kIndex != -1) {
num = 1;
// 易错点2:考虑下标越界
for (int i = kIndex - 1; i >= 0 && array[i] == k; i--)
num++;
for (int i = kIndex + 1; i < array.length && array[i] == k; i++)
num++;
}
return num;
}
/*
* 二分查找
*/
private int binaryFind(int[] arr, int left, int right, int k) {
if (left > right)
return -1;
else if (left == right)
if (arr[left] == k)
return left;
else
return -1;
int mid = left + (right - left) / 2;
if (arr[mid] > k)
return binaryFind(arr, left, mid - 1, k);
else if (arr[mid] < k)
return binaryFind(arr, mid + 1, right, k);
else
return mid;
}
/*
* 方法二:直接用二分查找找到数组中第一个k和最后一个k
*/
public int GetNumberOfK_2(int[] array, int k) {
if (array == null)
return -1;
int firstK = getFirstK(array, 0, array.length - 1, k);
int lastK = getLastK(array, 0, array.length - 1, k);
if(firstK==-1)
return 0;
return lastK - firstK+1;
}
/*
* 查找第一个k的下标
*/
private int getFirstK(int[] arr, int left, int right, int k) {
//递归终止条件
if (left > right)
return -1;
else if (left == right)
if (arr[left] == k)
return left;
else
return -1;
int mid = left + (right - left) / 2;
if (arr[mid] > k)
return getFirstK(arr, left, mid - 1, k);
else if (arr[mid] < k)
return getFirstK(arr, mid + 1, right, k);
//arr[mid] == k
else {
//如果mid==left,即mid为第一个k的下标
if (mid == left)
return mid;
//否则,继续递归
else {
if (arr[mid - 1] != k)
return mid;
else
return getFirstK(arr, left, mid - 1, k);
}
}
}
/*
* 查找最后一个k的下标
*/
private int getLastK(int[] arr, int left, int right, int k) {
if (left > right)
return -1;
else if (left == right)
if (arr[left] == k)
return left;
else
return -1;
int mid = left + (right - left) / 2;
if (arr[mid] > k)
return getLastK(arr, left, mid - 1, k);
else if (arr[mid] < k)
return getLastK(arr, mid + 1, right, k);
else {
if (mid == right)
return mid;
else {
if (arr[mid + 1] != k)
return mid;
else
return getLastK(arr, mid + 1, right, k);
}
}
}
}