题目描述
统计一个数字在排序数组中出现的次数。
看到二分查找,想到可以用二分查找,找到数k的位置后,向前向后顺序遍历,累计k出现的次数。
时间复杂度O(n)
#include<climits>
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k) {
int len = data.size();
if(len == 0) return 0;
int count = 0;
int pos = GetNumberOfKCore(data, k, 0, len - 1);
if(pos == INT_MIN)
return 0;
else
{
for(int i = pos; i >= 0; --i)
{
if(data[i] == k)
count++;
}
for(int j = pos + 1; j < len; j++)
{
if(data[j] == k)
count++;
}
return count;
}
}
int GetNumberOfKCore(vector<int>& data, int k, int start, int end)
{
if(start == end && data[start] != k)
{
return INT_MIN;
}
int mid = (start + end) / 2;
if(data[mid] == k)
return mid;
else if(data[mid] < k)
GetNumberOfKCore(data, k, mid+1, end);
else
GetNumberOfKCore(data, k, start, mid - 1);
return mid;
}
};
函数GetNumberOfKCore 递归找k的位置pos时,开始没有最后一句return mid,显示内存过大,即递归不能正常结束。加上之后调试成功。对递归理解还是不够深刻。
但是向左向右遍历过程中,有可能进行O(n)次,时间复杂度也是O(n)了,跟顺序遍历没有区别............
时间复杂度O(logn)(调试不通过)
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k) {
int len = data.size();
if(len == 0) return 0;
int count = 0;
int first = GetFirstK(data, len, k, 0, len - 1);
int last = GetLastK(data, len, k, 0, len - 1);
if(first > -1 && last > -1)
count = last - first + 1;
return count;
}
int GetFirstK(vector<int> &data, int length, int k, int start, int end)
{
if(start > end)
return -1;
int midIndex = (start + end) / 2;
int midData = data[midIndex];
if(midData == k)
{
if((midIndex > start && data[midIndex - 1] != k) || midIndex == 0)
return midIndex;
else
end = midIndex - 1;
}
else if(midData > k)
end = midIndex - 1;
else
start = midIndex + 1;
return GetFirstK(data, length, k, start, end);
}
int GetLastK(vector<int> &data, int length, int k, int start, int end)
{
if(start > end)
return -1;
int midIndex = (start + end) / 2;
int midData = data[midIndex];
if(midData == k)
{
if((midIndex < end && data[midIndex + 1] != k) || midIndex == length - 1)
return midIndex;
else
start = midIndex + 1;
}
else if(midData > k)
end = midIndex - 1;
else
start = midIndex + 1;
return GetLastK(data, length, k, start, end);
}
};
循环写法:
public class Solution {
public int GetNumberOfK(int [] array , int k) {
int length = array.length;
if(length == 0){
return 0;
}
int firstK = getFirstK(array, k, 0, length-1);
int lastK = getLastK(array, k, 0, length-1);
if(firstK != -1 && lastK != -1){
return lastK - firstK + 1;
}
return 0;
}
//递归写法
private int getFirstK(int [] array , int k, int start, int end){
if(start > end){
return -1;
}
int mid = (start + end) >> 1;
if(array[mid] > k){
return getFirstK(array, k, start, mid-1);
}else if (array[mid] < k){
return getFirstK(array, k, mid+1, end);
}else if(mid-1 >=start && array[mid-1] == k){
return getFirstK(array, k, start, mid-1);
}else{
return mid;
}
}
//循环写法
private int getLastK(int [] array , int k, int start, int end){
int length = array.length;
int mid = (start + end) >> 1;
while(start <= end){
if(array[mid] > k){
end = mid-1;
}else if(array[mid] < k){
start = mid+1;
}else if(mid+1 < end && array[mid+1] == k){
start = mid+1;
}else{
return mid;
}
mid = (start + end) >> 1;
}
return -1;
}
}