题目
统计一个数字在排序数组中出现的次数
方法一
暴力法 咔咔的循环就往上整就得了,但是违背了出题的本意,想考察你排序数组,没体现出来。但是好歹也算一个方法,写上去哈哈
代码
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k) {
int n=data.size();
int count=0;
for(int i=0;i<n;i++)
{
if(k==data[i])
count++;
}
return count;
}
};
方法二
就是用C++ stl里面的lower_bound和upper_bound,lower_bound是找出不小于即大于等于的第一个数的下标 ;upper_bound是找出大于的第一个数的下标。
ower_bound( )和upper_bound( )都是利用二分查找的方法在一个排好序的数组中进行查找的。
在从小到大的排序数组中,
lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
代码
class Solution
2 {
3 public:
4 int GetNumberOfK(vector<int> data ,int k)
5 {
6 int s1 = lower_bound(data.begin(),data.end(),k)-data.begin();
7 int s2 = upper_bound(data.begin(),data.end(),k)-data.begin();
return s2-s1;
10 }
11 };
方法三
二分法 不断缩小范围
1.先找出第一次出现的下标值,设left,mid,right分别代表数组的起始,中间,结束的下标。
若数组中间的数a[mid]大于k,则right = mid -1;
若数组中间的数a[mid]小于k,则left = mid+1;
若数组中间的数a[mid]等于k,判断a[mid-1] 是否等于k,若不等于,说明是第一次出现的下标,返回mid下标;若等于,则说明第一次出现的下标还在mid的左边,right = mid -1;
递归重复以上过程。
2.再找出最后出现的下标,原理同上。
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k)
{
if(data.empty())
return 0;
int first=getFirst(data,0,data.size()-1,k);
int last=getLast(data,0,data.size()-1,k);
int count=0;
if(first>-1&&last>-1)
count=last-first+1;
return count;
}
int getFirst(vector<int> data,int left,int right,int k){//用递归方式实现二分查找
if(left>right)
return -1;
int mid=(left+right)/2;
if (data[mid]==k)
{
if(mid>0&&data[mid-1]!=k||mid==0)
{
return mid;
}
else
right=mid-1;
}
else if(data[mid]<k)
left=mid+1;
else
right=mid-1;
return getFirst(data,left,right,k);
}
int getLast(vector<int>data,int left,int right,int k)
{
if(left>right)
return -1;
int mid=(left+right)/2;
if(data[mid]==k)
{
if(mid<data.size()-1&&data[mid+1]!=k||mid==data.size()-1)
return mid;
else
left=mid+1;
}
else if(data[mid]<k)
left=mid+1;
else if(data[mid]>k)
right=mid-1;
return getLast(data,left,right,k);
}
};
一定要注意,getFirst函数里如果不加上
if(left>right)
return -1;
编译是会报错,显示内存超出的;
我在这卡了半天才找到是这个原因。