在排序数组中查找数字
题目描述:
统计一个数字在排序数组中出现的次数。
思路:既然输入的数组是排序的,那么我们就能很自然的想到利用二分查找算法,但是直接查找,如果该数组全是该数字那么复杂度为O(n),和不用二分查找复杂度相同,所以我们使用二分查找直接差第一个和最后一个k的位置,复杂度为O(logn)。
代码一直接二分查找该数字,复杂度为O(n):
class Solution {
public:
int GetNumber0fkCore(vector<int>&data, int start, int end, int k){
if (start > end)return 0;
int mid = (start + end) / 2;
if (data[mid] == k){
int result = 1;
for (int i = mid + 1; i <= end; i++){
if (data[i] != k)break;
result++;
}
for (int j = mid - 1; j >= start; j--){
if (data[j] != k)break;
result++;
}
return result;
}
if (data[mid] > k){
return GetNumber0fkCore(data, start, mid - 1, k);
}
else{
return GetNumber0fkCore(data, mid + 1, end, k);
}
}
int GetNumberOfK(vector<int> data, int k) {
if (data.empty())return 0;
return GetNumber0fkCore(data, 0, data.size() - 1, k);
}
};
代码二查找第一个和最后一个k的位置复杂度为O(logn):
class Solution {
public:
int GetFirstK(const vector<int>&data,int start,int end,int k){//采用循环法
while (start <= end){
int mid = (start + end) >> 1;
if (data[mid] > k){
end = mid - 1;
}
else if (data[mid] < k){
start = mid + 1;
}
else if (mid - 1 >= start && data[mid - 1] != k||mid==start){
return mid;
}
else
end = mid - 1;
}
return -1;
}
int GetLastK(const vector<int>&data, int start, int end, int k){//采用递归法
if (start > end)return -1;
int mid = (start + end) >> 1;
if (data[mid] > k)return GetLastK(data, start, mid - 1, k);
else if (data[mid] < k)return GetLastK(data, mid + 1, end, k);
else if (data[mid + 1] != k&&mid + 1 <= end||mid==end)return mid;
else return GetLastK(data, mid+1, end, k);
}
int GetNumberOfK(vector<int> data, int k) {
if (data.empty())return 0;
int first = GetFirstK(data, 0, data.size() - 1, k);
int last = GetLastK(data, 0, data.size() - 1, k);
if (first != -1 && last != -1){
return last - first + 1;
}
return 0;
}
};