如何回归正面发生

时间:2015-06-12 03:42:01

标签: c algorithm binary-search

我有一个函数,当给定零索引数组A的N个整数,按非递减顺序排序,和一些整数X,在A中查找X。如果X存在于A中,则返回正数A中出现X的情况。否则,函数返回-1。

它应该像这样工作:

  • 如果我有A [0] = 1,A [1] = 1且X = 1则应该返回0,因为A [0] = 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;
}

3 个答案:

答案 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 - 1max + 1之间的每个数字,其中许多未找到当然因为数组中只有偶数值。它的输出结构很冗长,但有一些断言可以给出结果:如果结果有问题,应该触发断言。