トピック1:ソート配列に表示される数字の回数
[ソート配列に表示された統計数の数。{1,2,3,3,3,3,4}と番号3、4 3によって生じる、出力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;
}
};
方法2:改善されたバイナリ検索
図1に示すように、分析
改変二分探索法を用いてkは検索対象の数であります
- 中間アレイは、前者上のK数kより大きい場合
- 中間アレイは数kよりも小さい場合には、kの後半に配置されています
- 中間配列番号kが等しい場合、必要がkの前半の開始位置、終了位置kの後半を検出するために継続します。この方法の時間複雑です
- 再帰と非再帰2つの実装方法
図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;
}
};
方法3:STLコンテナみとめを使用します
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);
}
};