版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/nwpubear/article/details/81915247
判断一个有序数组中一个数字出现的次数
首先可以想到二分法,但是二分法只是找到其中一个的位置,这个时候不能确定个数
为了能够确定个数,可以有一个简单的方法,一个一个往前数,一个一个往后面数,直到数到边界为止,代码如下
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k) {
int index=binarySearch(data,0,data.size()-1,k);
if(index==-1)
return 0;
int indexleft=index;
int indexright=index;
while(indexleft>0 && data[indexleft-1]==k)
indexleft--;
while(indexright<data.size()-1 && data[indexright+1]==k)
indexright++;
return indexright-indexleft+1;
}
int binarySearch(std::vector<int> v,int left,int right,int k){
while(left<=right){
int middle=(left+right)/2;
if(v[middle]==k)
return middle;
else if(v[middle]<k)
left=middle+1;
else
right=middle-1;
return -1;
}
};
改进:可以看到这里使用了一次二分法,但是后面寻找边界的时候没有利用到前面和后面仍然是有序这个条件,仍然可以用二分法寻找,对于左边,只要它前面还有一个和它一样的数,那么久二分法查找[0,indexleft-1],直到不满足条件,返回indexleft,对于右边,如果右边还有一个相同的数,那么indexright+1,继续二分查找,直到不满足,最后indexleft和indexright就是边界。代码如下
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k) {
int index=binarySearch(data,0,data.size()-1,k);
if(index==-1)
return 0;
int indexleft=index;
int indexright=index;
while(indexleft>0 && data[indexleft-1]==k){
indexleft=binarySearch(data,0,indexleft-1,k);
}
while(indexright<data.size()-1 && data[indexright+1]==k){
indexright=binarySearch(data,indexright+1,data.size()-1,k);
}
return (indexright-indexleft+1);
}
int binarySearch(std::vector<int> v,int left,int right,int k){
while(left<=right){
int middle=(left+right)/2;
if(v[middle]==k)
return middle;
else if(v[middle]<k)
left=middle+1;
else
right=middle-1;
}
return -1;
}
};
总结:上面第二种算法明显优于第一种,尤其是在数据量大的情况下。