检查是否存在和0的子数组

时间:2018-06-14 08:36:47

标签: c arrays

请找到这段代码中的漏洞,检查给定数组中是否存在总和为0的子数组(我没有得到所需的输出)。我是编程新手,所以欢迎任何提示,建议。我真的很想改进。另外,如果我可以使用其他逻辑,请在评论中告诉我。

#include <stdio.h>
#include <stdlib.h>
int compare(const void* a,const void* b);
void FindO(int * A, int n);

int main()
{
    int i,n;
    int A[] = {-7,-4,-3,1,2,3,10};
    n = sizeof(A)/sizeof(A[0]);
    qsort(A,n, sizeof(int), compare);
    printf("The sorted array is: ");
    for (i = 0;i < n; i++)
    {
        printf("%d ", A[i]);
        }
    FindO(A, n);
    return 0;
    }

int compare(const void* a,const void* b)
{
    int l = *(int *)a;
    int r = *(int *)b;

    return (l-r);
    }

void FindO(int * A, int n)
{
    int mid = n/2;
    int i, j = mid;
    int sum = A[mid];
    printf("\n%d ", sum);
    while(i >= 0 && j <n)
    {
        if(sum ==0)
        {printf("\nFound it!");
            return;}
        else if(sum > 0)
        {
            i--;
            sum = sum + A[i];

            }
        else
        {
            j++;
            sum = sum + A[j];

            }
        }
    if(sum !=0)
    {printf("\nNot found Buddy!");
        }
    }

2 个答案:

答案 0 :(得分:1)

你没有说你的问题是什么。 但首先,您不会初始化i,这很可能会在您使用它时导致分段错误:

 while(i >= 0 && j <n)

或随后对其的引用。

您可以使用,逗号分隔变量,但初始化:

int i, j = mid;

仅影响j而非i

答案 1 :(得分:1)

我不知道你的算法如何获得数组的所有子数组,所以我编写了自己的解决方案。
这个用递归计算数组中子数组的所有元素,并检查总和是否等于零:

void FindO_in(const int *A, size_t n, int sum, size_t numslen)
{
    assert(A != NULL);
    assert(n >= 0);
    assert(numslen >= 0);

    if (n == 0) {
        if (numslen == 0) {
            // no numbers summed, ignored
            return;
        }
        if (sum != 0) return;
        if (sum == 0) {
            printf("Zero pal!");
        } else {
            printf("Not zero buddy!");
        }
        printf("\n");
        return;
    }
    --n;

    // next without incrementing sum
    FindO_in(&A[1], n, sum, numslen);

    // protec against overflow
    assert(!(A[0] > 0 ? (sum > INT_MAX - A[0]) : (sum < INT_MIN - A[0])));
    // next with incremented sum
    sum += A[0];
    ++numslen;
    FindO_in(&A[1], n, sum, numslen);
}

void FindO(const int *A, size_t n)
{
    FindO_in(A, n, 0, 0);
}

以下是更通用的解决方案。首先,我使用递归生成数组的所有子数据。然后对于每个子数组,我调用一个回调函数,该函数检查该子数组的元素总和是否等于零。

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <assert.h>

#define try(expr)  ((expr) ? (void)0 : (assert(expr), (void)fprintf(stderr, "Expression `%s` failed\n", #expr), abort()))

static void check0(const int *arr, size_t n)
{
    int sum = 0;
    for(size_t i = 0; i < n; ++i) {
        try(!(arr[0] > 0 ? (sum > INT_MAX - arr[0]) : (sum < INT_MIN - arr[0])));
        sum += arr[i];
    }
    if (sum != 0) return;
    printf("The sum of numbers {");
    for(size_t i = 0; i < n; ++i) {
        printf(" %d", arr[i]);
    }
    printf("} is equal %d. ", sum);
    if (sum == 0) {
        printf("Zero pal!");
    } else {
        printf("Not zero buddy!");
    }
    printf("\n");
}

static void gensubarrays_in(const int *arr, size_t n, int *subarr, size_t subarrlen, void (*callback)(const int*, size_t))
{
    assert(arr != NULL);
    assert(n >= 0);
    assert(subarr != NULL);

    if (n == 0) {
        // empty subarray - ignore
        if (subarrlen == 0) return;

        callback(subarr, subarrlen);

        return;
    }
    --n;
    gensubarrays_in(&arr[1], n, subarr, subarrlen, callback);
    subarr[subarrlen++] = arr[0];
    gensubarrays_in(&arr[1], n, subarr, subarrlen, callback);
}

static void gensubarrays(const int *arr, size_t n, void (*callback)(const int*, size_t))
{
    // just a temp variable, to know, which numbers are summed
    int *subarr = calloc(sizeof(int), n);
    try(subarr != NULL);
    gensubarrays_in(arr, n, subarr, 0, callback);
    free(subarr);
}

int main()
{
    int A[] = {-7,-4,-3,1,2,3,10};
    const size_t n = sizeof(A)/sizeof(A[0]);

    printf("The array is: ");
    for (size_t i = 0; i < n; i++) {
        printf("%d ", A[i]);
    }
    printf("\n");

    gensubarrays(A, n, check0);

    return 0;
}

:)