分析题目:数组是已排序好的,找出给定数字key出现的次数,
方法1、最直观的方法就是遍历一遍数组,时间复杂度O(N)
方法2、可以借助二分查找,时间复杂度为O(logN)
找出最左边出现的key出现的位置,找出最右边key出现的位置。
size_t getLow(int *array,int size, int k)
{
size_t left = 0;
size_t right = size - 1;
while (left < right)
{
int mid = (left + right) / 2;
if (array[mid] >= k)
right = mid;
else
left = mid + 1;
}
return left;
}
size_t getRight(int *array, int size, int k)
{
size_t left = 0;
size_t right = size - 1;
while (left < right)
{
int mid = (left + right) / 2;
if (array[mid] <= k)
left = mid;
else
right = mid -1;
}
return right;
}
int main()
{
int arr[] = { 0, 1, 1, 2, 2, 2, 2, 4, 4, 4 };
int size = sizeof(arr) / sizeof(*arr);
size_t left = getLow(arr, size, 2);
size_t right = getRight(arr, size, 2);
size_t count = right - left + 1;
return 0;
}
递归算法
注意:参数count为引用。
void getCount(int *array,int left,int right ,int k,int& count)
{
if (left > right)
return;
int mid = (left + right) / 2;
if (array[mid] == k)
{
++count;
getCount(array, left, mid - 1, k, count);
getCount(array, mid + 1, right, k, count);
}
else if (array[mid] > k)
getCount(array, left, mid - 1, k, count);
else
getCount(array, mid + 1, right, k, count);
}
二分查找
如果是开区间的话,right = length,left < right,right = mid.
//[] 闭区间
int BinSearch(int arr[],int length, int key)
{
int left = 0;
int right = length - 1;
int mid = 0;
while (left <= right)
{
mid = (left + right) >> 1;
if (arr[mid] < key)
left = mid + 1;
else if (arr[mid] > key)
right = mid - 1;
else
return mid;
}
return -1;
}
* 在有序数组中,查找第一个大于k的数字 upper_bound函数*
int FirstGreat(int *arr,int size,int k)
{
int left = 0, right = size - 1;
while (left <= right)
{
int mid = (left + right) / 2;
if (arr[mid] <= k)
left = mid + 1;
else
right = mid - 1;
}
return left < size ? left : -1;
}
有序数组中,查找第一个大于等于k的数字,lower_bound函数
int FirstGreatOrEqual(int *arr,int size,int k)
{
int left = 0, right = size - 1;
while (left <= right)
{
int mid = (left + right) / 2;
if (arr[mid] < k)
left = mid + 1;
else
right = mid - 1;
}
return left < size ? left : -1;
}