我有一个函数,当给定零索引数组A的N个整数,按非递减顺序排序,和一些整数X,在A中查找X。如果X存在于A中,则返回正数A中出现X的情况。否则,函数返回-1。
它应该像这样工作:
但它没有归还我想要的东西。有人能帮我吗? 这是我的代码:
int Number(int *A, int N, int X) {
int r, m, l;
if (N == 0) {
return -1;
}
l = 0;
r = N - 1;
while (l < r) {
m = (l + r) / 2;
if (A[m] > X) {
r = m - 1;
} else {
l = m;
}
}
if (A[l] == X) {
return l;
}
return -1;
}
答案 0 :(得分:2)
二进制搜索不保证找到的位置是数组中此数字的第一次出现。
如果我有A [0] = 1,A [1] = 1且X = 1它应该返回0,因为A [0] = 1
这意味着在这个sutiation中答案“1”是正确的,因为A [1] = 1。
您需要手动遍历数组以查找第一个不匹配值(或数组开头)。优化是可能的,但只有当你有一个具有大量重复值的极大数组时才需要进行优化。
您也可以尝试默认的二进制搜索方法:
int Number(int *A, int N, int X) {
int r, m, l;
if (N == 0) {
return -1;
}
l = 0;
r = N - 1;
while (l < r) {
m = (l + r) / 2;
if (A[m] == X)
return m;
if (A[m] > X) {
r = m - 1;
} else {
l = m + 1;
}
}
return -1;
}
答案 1 :(得分:2)
我尝试了一种稍微不同的策略。它似乎有效。
#include <stdio.h>
int Number(int *A, int N, int X) {
int r, m, l;
if (N == 0) {
return -1;
}
l = 0;
r = N; // Not N-1
while (l < r) {
m = (l + r) / 2;
// Debugging output. Track how l, m, and r change.
printf("l: %d, m: %d, r: %d\n", l, m, r);
// A slightly different strategy for narrowing
// the interval.
if (A[m] < X) {
l = m+1;
} else {
r = m;
}
}
if (A[l] == X) {
return l;
}
return -1;
}
void test1()
{
int A[] = {1, 1};
printf("%d\n", Number(A, 2, 1));
}
void test2()
{
int A[] = {0, 1, 1};
printf("%d\n", Number(A, 3, 1));
}
void test3()
{
int A[] = {0, 0, 1, 1, 2, 2};
printf("%d\n", Number(A, 6, 1));
printf("%d\n", Number(A, 5, 1));
printf("%d\n", Number(A, 4, 1));
}
int main()
{
test1();
test2();
test3();
return 0;
}
输出:
l: 0, m: 1, r: 2
l: 0, m: 0, r: 1
0
l: 0, m: 1, r: 3
l: 0, m: 0, r: 1
1
l: 0, m: 3, r: 6
l: 0, m: 1, r: 3
l: 2, m: 2, r: 3
2
l: 0, m: 2, r: 5
l: 0, m: 1, r: 2
2
l: 0, m: 2, r: 4
l: 0, m: 1, r: 2
2
答案 2 :(得分:0)
以下是Jon Bentley的书Programming Pearls, 2nd Edition:
中的修改二进制搜索/*
** Modified binary search.
** Find lowest occurrence of value in array (if there is more than one)
*/
#include <assert.h>
#include <stdio.h>
/*
** From J Bentley "Programming Pearls, 2nd Edition", Section 9.3
** Locate the first occurrence of t in x[0..n-1].
** Assume n >= 0, and the hypothetical elements x[-1] < t and x[n] > t
** without accessing either fictitious element.
*/
static
int bsearchf(const int *x, int n, int t)
{
int l = -1;
int u = n;
assert(n >= 0);
while (l + 1 != u)
{
/* Invariant: x[l] < t && x[u] >= t && l < u */
int m = (l + u) / 2;
//printf(" t = %d, l = %d, u = %d, m = %d, x[%d] = %d\n",
// t, l, u, m, m, x[m]);
if (x[m] < t)
l = m;
else
u = m;
}
if (u >= n || x[u] != t)
return -1;
assert(u >= 0 && u < n);
return u;
}
int main(void)
{
const int data[] =
{
0, 0, 0, 2, 2, 2,
/* 2, 2, 2, 2, 2, 2, */
4, 6, 6, 6, 8, 8,
};
enum { DATA_SIZE = sizeof(data) / sizeof(data[0]) };
/* Check monotonic non-decreasing data */
for (int j = 0; j < DATA_SIZE - 1; j++)
assert(data[j] <= data[j+1]);
/* Every starting point in the data array */
for (int j = 0; j < DATA_SIZE; j++)
{
const int *base = &data[j];
/* Every valid data length for the remainder of the data array */
for (int k = DATA_SIZE - j; k > 0; k--)
{
int lo = base[0] - 1;
int hi = base[k-1] + 2;
printf("N = %d", k);
for (int m = 0; m < k; m++)
printf(" A[%d]: %d", m, base[m]);
putchar('\n');
/* For every value from 1 less than the minimum to one more than the maximum */
for (int i = lo; i < hi; i++)
{
int r = bsearchf(base, k, i);
printf("V = %2d, : R = %2d, C = %2d : %s\n",
i, r, (r < 0) ? -1 : base[r],
(r < 0) ? "missing" : "found");
if (r == -1)
{
for (int n = 0; n < k; n++)
assert(base[n] != i);
}
assert(r == -1 || (base[r] == i && (r == 0 || base[r-1] < i)));
}
}
}
return 0;
}
主程序是一个测试程序,它检查数组data
的每个子序列,并尝试查找该数组中min - 1
和max + 1
之间的每个数字,其中许多未找到当然因为数组中只有偶数值。它的输出结构很冗长,但有一些断言可以给出结果:如果结果有问题,应该触发断言。