题目:
统计一个数字在排序数组中出现的次数。
方法一:暴力匹配
时间复杂度:O(n)
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k)
{
int count=0;
for(int i=0;i<data.size();i++)
{
if(data[i]==k)
count++;
else if(data[i]>k)
break;
}
return count;
}
};
方法二:二分法
由于是排序数组,可以使用二分查找,找到第一个K和最后一个K 二者位置相减
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k)
{
int len=data.size();
int FirstK=GetFirstK(data,k,0,len-1);
int LastK=GetLastK(data,k,0,len-1);
if(FirstK!=-1&&LastK!=-1)
return LastK-FirstK+1;
return 0;
}
private:
int GetFirstK(vector<int>data,int k,int begin,int end)
{
if(begin>end)
return -1;
int mid=(begin+end)/2;
if(data[mid]>k)
return GetFirstK(data, k, begin, mid-1);
else if(data[mid]<k)
return GetFirstK(data, k, mid+1, end);
else if(mid-1>=0&&data[mid-1]==k)
return GetFirstK(data, k, begin, mid-1);
else
return mid;
}
int GetLastK(vector<int>data,int k,int begin,int end)
{
if(begin>end)
return -1;
int mid=(begin+end)/2;
if(data[mid]>k)
return GetLastK(data, k, begin, mid-1);
else if(data[mid]<k)
return GetLastK(data, k, mid+1, end);
else if(mid+1<=end&&data[mid+1]==k)
return GetLastK(data, k, mid+1, end);
else
return mid;
}
};
下面用循环来代替递归
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k)
{
int len=data.size();
int FirstK=GetFirstK(data,k,0,len-1);
int LastK=GetLastK(data,k,0,len-1);
if(FirstK!=-1&&LastK!=-1)
return LastK-FirstK+1;
return 0;
}
private:
int GetFirstK(vector<int>data,int k,int begin,int end)
{
int mid=(begin+end)/2;
while(begin<=end)
{
if(data[mid]>k)
end=mid-1;
else if(data[mid]<k)
begin=mid+1;
else if(mid-1>=0&&data[mid-1]==k)
end=mid-1;
else
return mid;
mid=(begin+end)/2; //不要忘了重置mid
}
return -1;
}
int GetLastK(vector<int>data,int k,int begin,int end)
{
int mid=(begin+end)/2;
while(begin<=end)
{
if(data[mid]>k)
end=mid-1;
else if(data[mid]<k)
begin=mid+1;
else if(mid+1<=end&&data[mid+1]==k)
begin=mid+1;
else
return mid;
mid=(begin+end)/2;
}
return -1;
}
};
方法三:
同样采用二分法,不过二分法找出的是任意一个出现k的位置,从该位置开始,前后遍历,递加计数器,得到k出现的个数
class Solution {
public:
int PositionOfK(vector<int>data,int k,int begin,int end)
{
int mid=(begin+end)/2;
while(begin<=end)
{
if(data[mid]==k)
return mid;
else if(data[mid]>k)
end=mid-1;
else
begin=mid+1;
mid=(begin+end)/2;
}
return -1;
}
int GetNumberOfK(vector<int> data ,int k)
{
int len=data.size();
int position=PositionOfK(data,k,0,len-1);
if(position==-1)
return 0;
int count=0;
int i=position;
while(data[i]==k&&i<=len-1)
{
count++;
i++;
}
i=position-1;
while(data[i]==k&&i>=0)
{
count++;
i--;
}
return count;
}
};
方法四:
因为data中都是整数,所以可以稍微变一下,不是搜索k的两个位置,而是搜索k-0.5和k+0.5这两个数应该插入的位置,然后相减即可。
class Solution {
public:
int MyInsert(vector<int>data,double num)
{
int len=data.size();
int begin=0,end=len-1;
while(begin<=end)
{
int mid=(begin+end)/2;
if(data[mid]>num)
end=mid-1;
if(data[mid]<num)
begin=mid+1;
}
return end;
}
int GetNumberOfK(vector<int> data ,int k)
{
return MyInsert(data,k+0.5)-MyInsert(data,k-0.5);
}
};