统计一个数字在升序数组中出现的次数。
解题思路
- 二分查找+顺序遍历(O(n))
- 二分查找变体
上代码(C++很香)
法二:二分查找变体
首先,排序数组的查找,应该最先想到二分查找,能做到O(logn)的复杂度优势。然后,统计出现次数,如果用遍历前后的数量的方式,可能会达到O(n)的复杂度,所以,结合二分查找的变体,首先查找第一次出现的位置,然后查找最后一次出现的位置,两者作差即为次数。
顺便复习一下二分查找与二分查找的变体。
- 排序数组中第一次出现k的位置
- 排序数组中最后一次出现k的位置
- 排序数组中第一个大于等于k的位置
- 排序数组中第一个小于等于k的位置
// 排序数组中第一次出现k的位置
int binarySearchFirst(vector<int> num, int k, int length){
int low = 0;
int high = length - 1;
int middle = 0;
while(low <= high){
middle = low + ((high - low) >> 1);
if(num[middle] == k){
if(middle > 0 && num[middle - 1] != k || middle == 0)
return middle;
else
high = middle - 1;
}
else if(num[middle] > k)
high = middle - 1;
else
low = middle + 1;
}
return -1;
}
// 最后一次出现k的位置
int binarySearchLast(vector<int> num, int k, int length){
int low = 0;
int high = length - 1;
int middle = 0;
while(low <= high){
middle = low + ((high - low) >> 1);
if(num[middle] == k){
if(middle < length - 1 && num[middle + 1] != k || middle == length - 1)
return middle;
else
low = middle + 1;
}
else if(num[middle] > k)
high = middle - 1;
else
low = middle + 1;
}
return -1;
}
int GetNumberOfK(vector<int> data ,int k) {
// 首先查找第一次出现的位置
int firstT = binarySearchFirst(data, k, data.size());
if(firstT == -1)
return 0;
// 查找最后一次出现的位置
int lastT = binarySearchLast(data, k, data.size());
return lastT - firstT + 1;
}