数字在排序数组中出现的次数
统计一个数字在排序数组中出现的次数。
题解:
1)暴力穷举法:
一一比较,输出次数
2)二分法——相同数字遍历法:
通过二分法,找到目标数字在排序数组中的一个位置。通过该位置用两个指针对其进行前后遍历,当指针指向的数字不为目标数字时停止。
代码如下:
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k) {
if(data.size()==0) return 0;
int res=0;
int l=0;
int r=data.size()-1;
if(data[l]==k&&data[r]==k) return r+1;
int mid=(l+r)/2;
while(l<=r){
if(data[mid]==k)
break;
if(data[mid]<k)
l=mid+1;
if(data[mid]>k)
r=mid-1;
mid=(l+r)/2;
}
int mid1=mid;
while(data[mid1]==k&&mid1>=l){
mid1--;res++;
}
while(data[mid+1]==k&&mid<=r){
mid++;res++;
}
return res;
}
}
2)二分法——查找前后首次和最后一次出现的位置:
通过二分法,找到目标数字在数组中的一个位置,然后根据前后指针,将数组分为两个子数组,在左数组中查找首次出现目标数字的位置;在右数组中查找最后一次出现目标数字的位置,二者相减+1.
代码如下:
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k) {
/*if(data.size()==0) return 0;
int res=0;
int l=0;
int r=data.size()-1;
if(data[l]==k&&data[r]==k) return r+1;
int mid=(l+r)/2;
while(l<=r){
if(data[mid]==k)
break;
if(data[mid]<k)
l=mid+1;
if(data[mid]>k)
r=mid-1;
mid=(l+r)/2;
}
int mid1=mid;
while(data[mid1]==k&&mid1>=l){
mid1--;res++;
}
while(data[mid+1]==k&&mid<=r){
mid++;res++;
}
return res;*/
if(data.size()==0) return 0;
int res=0;
int l=0;
int r=data.size()-1;
if(data[l]==k&&data[r]==k) return r+1;//数组全为目标数字
if(r==l&&data[l]!=k) return 0; //数组大小为1,且不为目标数字
int mid;
while(l<=r){
int mid=(l+r)>>1;
if(data[mid]==k) break;//首次查找目标数字的一个位置
if(data[mid]<k) l=mid+1;
if(data[mid]>k) r=mid-1;
}
int r1=r;
int l1=mid;
r=mid-1;
while(l<=r){//查找目标首次出现位置
if(data[(l+r)/2]<k)
l=(l+r)/2+1;
else if((l+r)/2-1>=l && data[(l+r)/2-1]==k){
r=(l+r)/2-1;
}
else
break;
}
while(l1<=r1){//查找目标最后一次出现的位置
if(data[(l1+r1)/2]>k){
r1=(l1+r1)/2-1;
}
else if((l1+r1)/2+1<=r1 && data[(l1+r1)/2+1]==k)
l1=(l1+r1)/2+1;
else
break;
}
if((l1+r1)/2==(l+r)/2)//防止数组中不存在目标数字
return 0;
res=(l1+r1)/2-(l+r)/2+1;
return res;
}
};