1、题目描述
统计一个数字在排序数组中出现的次数。
2、思路
方法一:
直接遍历整个数组,与该数字做比对,统计它出现的次数。时间复杂度O(n)。
方法二:
先用二分查找找到第一个k的下标,再用二分查找找到最后一个下标,最后一个k小标减去第一个k下标并加1,就是k在数组中出现的次数。时间复杂度为O(logn)。
利用二分查找找到第一个k的下标的过程:
拿中间的数字和k作比较,如果中间的是数字比k大,则在前一部分继续 查找第一个k;如果中间的数字比k小,则在后一部分继续查找第一个k;如果中间的数字等于k,则判断中间数字的前一个数字是否等于k,如果等于k,则继续在前一部分查找第一个k,否则,当前数字就是第一个k。
利用二分查找找到最后一个k的下标的过程与查找第一个k下标的过程类似。
3、代码
方法一代码实现:
public
class
Solution {
public
int
GetNumberOfK(
int
[] array ,
int
k) {
int
count=
0
;
for
(
int
i=
0
;i<array.length;i++){
if
(array[i]==k)
count++;
}
return
count;
}
}
|
方法二代码实现:
public class Solution {
/**
得到第一个k的索引
*/
int GetFirstK(int [] array,int k,int start,int end){
if(start > end){
return -1;
}
int middleIndex = (start + end) / 2;
int middleData = array[middleIndex];
if(middleData == k){//如果中间值等于k
if((middleIndex>0 && array[middleIndex-1]!=k) || middleIndex==0){//如果中间值的前一个数不为k或者中间值是第一个数
return middleIndex;
}else{//中间值的前一个数为k,则第一个k还在当前值的左边
end = middleIndex - 1;
}
}else if(middleData > k){//中间值大于k,说明第一个k在中间值左边
end = middleIndex - 1;
}else{
start = middleIndex + 1;//如果中间值小于k,说明第一个k在中间值右边
}
return GetFirstK(array,k,start,end);
}
/**
得到最后一个k的索引
*/
int GetLastK(int [] array,int k,int start,int end){
if(start > end){
return -1;
}
int middleIndex = (start+end)/2;
int middleData = array[middleIndex];
if(middleData == k){
if((middleIndex<array.length-1&&array[middleIndex+1]!=k) || middleIndex==array.length-1){//判断中间值的后一个值是否为k
return middleIndex;
}else{
start = middleIndex + 1;
}
}else if(middleData < k){
start = middleIndex + 1;
}else{
end = middleIndex - 1;
}
return GetLastK(array,k,start,end);
}
public int GetNumberOfK(int [] array , int k) {
int number = 0;
if(array.length > 0){//数组存在
int first = GetFirstK(array,k,0,array.length-1);
int last = GetLastK(array,k,0,array.length-1);
if(first>-1 && last>-1){
number = last - first + 1;
}
}
return number;//返回数字在数组中出现的次数
}
}