題目一:數字在排序數組中出現的次數
【統計一個數字在排序數組中出現的次數。如 {1,2,3,3,3,3,4}和數字3,由於3出現的4,所以輸出4】
方法一:直接遍歷
1、分析
直接遍歷數組,由於數組已經排好序了,所以當數組中出現了數字 k 時就開始統計其出現的次數。該方法的時間複雜度爲 ,還有更快的二分法。
2、代碼
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k) {
int len=data.size();
if(len<=0 || k<data[0] || k>data[len-1])
return 0;
int count=0;
vector<int>::const_iterator it=data.begin();
while(it!=data.end())
{
if((*it)==k)
++count;
it++;
}
return count;
}
};
方法二:改進的二分查找
1、分析
使用二分查找的改進方法:待查找數字爲 k
- 當數組中間的數字大於 k 時,則 k 位於前半段
- 當數組中間的數字小於 k 時,則 k 位於後半段
- 當數組中間的數字等於 k 時,需要繼續查出前半段中 k 的起始位置,後半段中 k 的結束位置。該方法的時間複雜度爲
- 該方法有遞歸和非遞歸的兩種實現方式
2、代碼
- 遞歸的方式
/*
* 使用遞歸的方式
*/
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k) {
if(data.empty())
return 0;
int firstIndex=GetFirstIndex(data,k,0,data.size()-1);
int lastIndex=GetLastIndex(data,k,0,data.size()-1);
int count=0;
if(firstIndex>-1 && lastIndex>-1)
count=lastIndex-firstIndex+1;
return count;
}
// 尋找第第一個k的下標
int GetFirstIndex(vector<int> &data,int k,int start,int end)
{
if(start>end)
return -1;
int mid=start+(end-start)/2;
if(data[mid]==k)
{
if((mid>start && data[mid-1]!=k) || mid==start)
return mid;
else
end=mid-1;
}
else if(data[mid]>k)
{
end=mid-1;
}
else
start=mid+1;
return GetFirstIndex(data,k,start,end);
}
// 尋找第二個k的下標
int GetLastIndex(vector<int> &data,int k,int start,int end)
{
if(start>end)
return -1;
int mid=start+(end-start)/2;
if(data[mid]==k)
{
if((mid<end && data[mid+1]!=k) || mid==end)
return mid;
else
start=mid+1;
}
else if(data[mid]>k)
{
end=mid-1;
}
else
start=mid+1;
return GetLastIndex(data,k,start,end);
}
};
- 非遞歸的方式
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k) {
if(data.empty())
return 0;
int firstIndex=GetFirstIndex(data,k,0,data.size()-1);
int lastIndex=GetLastIndex(data,k,0,data.size()-1);
int count=0;
if(firstIndex>-1 && lastIndex>-1)
count=lastIndex-firstIndex+1;
return count;
}
// 尋找第第一個k的下標
int GetFirstIndex(vector<int> &data,int k,int start,int end)
{
//初始中間位置,必須放在循環之外
int mid=start+(end-start)/2;
// 循環條件不可漏掉 start=end 的情況
while(start<=end)
{
if(data[mid]>k)
{
end=mid-1;
}
else if(data[mid]<k)
{
start=mid+1;
}
else
{
if((mid>start && data[mid-1]!=k)||mid==start)
{
return mid;
}
else
{
end=mid-1;
}
}
mid=start+(end-start)/2; //更新中間的位置
}
return -1;
}
// 尋找第二個k的下標
int GetLastIndex(vector<int> &data,int k,int start,int end)
{
int mid=start+(end-start)/2;
while(start<=end)
{
if(data[mid]>k)
{
end=mid-1;
}
else if(data[mid]<k)
{
start=mid+1;
}
else
{
if((mid<end && data[mid+1]!=k)||mid==end)
{
return mid;
}
else
{
start=mid+1;
}
}
mid=start+(end-start)/2;
}
return -1;
}
};
方法三:使用STL中的mutiple容器
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k) {
if(data.empty())
return 0;
multiset<int> mp;
for(auto &i:data)
{
mp.insert(i);
}
return mp.count(k);
}
};