题目描述
统计一个数字在排序数组中出现的次数
解题思想:
遇见排序数组,首先想到二分查找
利用二分查找,在数组中找到第一个k出现下标,再找到最后一个k,下标相减加一即可。
二分查找算法分析查找第一个k:先拿数组中间的数字和k进行比较,
1、如果中间的数字比k大,则k出现在数组的前半段,下一轮只需要在数组的前半段查找即可;
2、如果中间的数字比k大,则k出现在数组的后半段,下一轮只需要在数组的后半段查找即可;
3、如果中间的数字和k相等,则要判断这个数字是不是第一个k,
如果位于中间数字前一个数字不是k,则此时的中间数字就是第一个k;
如果位于中间数字前一个数字也是k,则即是说第一个k肯定在数组的前半段,下一轮我们需要在数组的前半段查找。
二分查找算法分析查找第后一个k:与上述类似
先拿数组中间的数字和k进行比较,
1、如果中间的数字比k大,则k出现在数组的前半段,下一轮只需要在数组的前半段查找即可;
2、如果中间的数字比k大,则k出现在数组的后半段,下一轮只需要在数组的后半段查找即可;
3、如果中间的数字和k相等,则要判断这个数字是不是第后一个k,
如果位于中间数字后一个数字不是k,则此时的中间数字就是第后一个k;
如果位于中间数字后一个数字也是k,则即是说第后一个k肯定在数组的后半段,下一轮我们需要在数组的后半段查找。
(1)自己根据思想写出来的
public class Solution
{
public int GetNumberOfK(int [] array , int k)
{
if(array==null||array.length==0)
return 0;
int low=0;
int high=array.length-1;
int firstK=getFirstK(array,k,low,high);
int lastK=getLastK(array,k,low,high);
if(firstK!=-1&&lastK!=-1)//要判断
return lastK-firstK+1;
return 0;
}
//递归
private int getFirstK(int[]array,int k,int low,int high){
if(low>high)//要判断
return -1;
int mid=(low+high)>>1;
if(array[mid]>k)
return getFirstK(array,k,low,mid-1);
else if(array[mid]<k)
return getFirstK(array,k,mid+1,high);
else{
if(mid-1>=0&&array[mid-1]==k)//要判断前一个==k?mid-1>=0很重要
return getFirstK(array,k,low,mid-1);
else
return mid;
}
}
//递归
private int getLastK(int[]array,int k,int low,int high){
if(low>high)//要判断
return -1;
int mid=(low+high)>>1;
if(array[mid]>k)
return getLastK(array,k,low,mid-1);
else if(array[mid]<k)
return getLastK(array,k,mid+1,high);
else{
if(mid+1<array.length &&array[mid+1]==k)//要判断后一个==k?mid+1<array.length很重要
return getLastK(array,k,mid+1,high);
else
return mid;
}
}
/*
//非递归写法
private int getLastK(int[]array,int k,int low,int high){
int mid=(low+high)>>1;
while(low<=high){
if(array[mid]>k)
high=mid-1;
else if(array[mid]<k)
low=mid+1;
else{
if(mid+1<array.length&&array[mid+1]==k)
low=mid+1;
else
return mid;
}
mid=(low+high)>>1;
}
return -1;
}*/
}