在 C 中使用 O(log(N)) 查找排序数组中数字的出现次数?
Finding the number of occurrences of a number in a sorted array with O(log(N)) in C?
如果我有一个排序数组 arr[]
包含 n
个元素,我怎样才能找到复杂度为 O(logn) 的某个数字 key
的出现次数?
例如:
对于
int arr[] = {0, 1, 2, 2, 6, 6, 6, 7};
int n = 8;
int key = 6;
int first, last;
我会得到3
.
我解决这个问题的方法是进行两次二进制搜索,一次搜索第一次出现 key
的索引,将结果保存在 int first
中。另一个搜索key
最后一次出现的索引,将结果保存在last
中。那么剩下要做的就是return
last - first + 1
.
但是当我开始编写问题代码时,我遇到了一个问题,我无法计算last
是什么导致了奇怪的结果。我一直在尝试调试我的代码但没有成功,有什么建议吗?
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
int ex2(int*, int, int);
int main()
{
int arr[] = {1, 4, 6, 6, 6, 7, 7, 8, 11, 14, 22};
printf("%d", ex2(arr, 11, 6));
return 0;
}
int ex2(int* a, int n, int x)
{
int low = 0, high = n - 1, mid, first = 0, last = 0;
// bin first
while (low <= high)
{
mid = (low + high) / 2;
if (a[mid] == x)
{
if (mid - 1 < low || a[mid - 1] < x)
{
first = mid;
break;
}
else
high = mid - 1;
}
if (a[mid] < x)
low = mid + 1;
else
high = mid - 1;
}
// bin last
low = 0;
high = n - 1;
while (low <= high)
{
mid = (low + high) / 2;
if (a[mid] == x)
{
if (mid + 1 > high|| a[mid + 1] > x)
{
last = mid;
break;
}
else
low = mid + 1;
}
if (a[mid] < x)
low = mid + 1;
else
high = mid - 1;
}
return last - first + 1;
}
当我 运行 它用于:
int arr[] = {1, 4, 6, 6, 6, 7, 7, 8, 11, 14, 22};
printf("%d", ex2(arr, 11, 6));
我得到 -1(因为 last
仍然是 0
不像 first
持有 2
的正确值 - > 0 - 2 + 1 = -1 ).
当我得到 3(6 出现 3 次)时。
将出现的两个地方 if (a[mid] < x)
更改为 else if (a[mid] < x)
。
否则,在 a[mid] == x
并且您设置 low
(在第一次搜索中)或 high
(在第二次搜索中)的情况下,代码将落入此a[mid] < x
的测试并错误地设置了另一个边界。插入 else
排除那个。
如果我有一个排序数组 arr[]
包含 n
个元素,我怎样才能找到复杂度为 O(logn) 的某个数字 key
的出现次数?
例如: 对于
int arr[] = {0, 1, 2, 2, 6, 6, 6, 7};
int n = 8;
int key = 6;
int first, last;
我会得到3
.
我解决这个问题的方法是进行两次二进制搜索,一次搜索第一次出现 key
的索引,将结果保存在 int first
中。另一个搜索key
最后一次出现的索引,将结果保存在last
中。那么剩下要做的就是return
last - first + 1
.
但是当我开始编写问题代码时,我遇到了一个问题,我无法计算last
是什么导致了奇怪的结果。我一直在尝试调试我的代码但没有成功,有什么建议吗?
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
int ex2(int*, int, int);
int main()
{
int arr[] = {1, 4, 6, 6, 6, 7, 7, 8, 11, 14, 22};
printf("%d", ex2(arr, 11, 6));
return 0;
}
int ex2(int* a, int n, int x)
{
int low = 0, high = n - 1, mid, first = 0, last = 0;
// bin first
while (low <= high)
{
mid = (low + high) / 2;
if (a[mid] == x)
{
if (mid - 1 < low || a[mid - 1] < x)
{
first = mid;
break;
}
else
high = mid - 1;
}
if (a[mid] < x)
low = mid + 1;
else
high = mid - 1;
}
// bin last
low = 0;
high = n - 1;
while (low <= high)
{
mid = (low + high) / 2;
if (a[mid] == x)
{
if (mid + 1 > high|| a[mid + 1] > x)
{
last = mid;
break;
}
else
low = mid + 1;
}
if (a[mid] < x)
low = mid + 1;
else
high = mid - 1;
}
return last - first + 1;
}
当我 运行 它用于:
int arr[] = {1, 4, 6, 6, 6, 7, 7, 8, 11, 14, 22};
printf("%d", ex2(arr, 11, 6));
我得到 -1(因为 last
仍然是 0
不像 first
持有 2
的正确值 - > 0 - 2 + 1 = -1 ).
当我得到 3(6 出现 3 次)时。
将出现的两个地方 if (a[mid] < x)
更改为 else if (a[mid] < x)
。
否则,在 a[mid] == x
并且您设置 low
(在第一次搜索中)或 high
(在第二次搜索中)的情况下,代码将落入此a[mid] < x
的测试并错误地设置了另一个边界。插入 else
排除那个。