C - 子集之和,需要更快的算法

标签 c algorithm

我试图找到等于给定数字的子集(1-3 长度)的总和。我写了这个算法,它工作正常,但太慢了。我如何更改此算法以使其更快?

int PrintCombinations(int * array, int userLenght) {
    int total = 0;

    for (int i = 0; i < GetArrayLenght(array); ++i) {
        if(userLenght == array[i]) {
            printf("%d = %d\n", userLenght, array[i]);
            ++total;
        }
    }

    for (int j = 0; j < GetArrayLenght(array); ++j) {
        for (int k = j; k < GetArrayLenght(array); ++k) {
            if(array[j] + array[k] == userLenght) {
                printf("%d = %d + %d\n", userLenght, array[j], array[k]);
                ++total;
            }
        }
    }

    for (int l = 0; l < GetArrayLenght(array); ++l) {
        for (int i = l; i < GetArrayLenght(array); ++i) {
            for (int j = i; j < GetArrayLenght(array); ++j) {
                if(array[l] + array[i] + array[j] == userLenght) {
                    printf("%d = %d + %d + %d\n", userLenght, array[j], array[l], array[i]);
                    ++total;
                }
            }
        }
    }

    return total;
}

最佳答案

您应该在循环之前计算一次数组的长度。目前它在每个循环的每次迭代中重新计算。如果此操作开销很大,将计算移出循环将是优化代码的一种非常有效的方法。

例如,如果 GetArrayLenght() 扫描数组以寻找终止值,将调用移出循环会使时间复杂度从 O(N4)O(N3)

第二步是以不同方式嵌套循环,避免搜索是否已经超出了总和的长度(假设所有长度 都是正数)。这不会改变时间复杂度,但仍然可以显着减少测试次数:

int PrintCombinations(int *array, int userLength) {
    int total = 0;
    int length = GetArrayLenght(array); 

    for (int l = 0; l < length; ++l) {
        if (array[l] > userLength)
            continue;

        if (array[l] == userLength) {
            printf("%d = %d\n", userLength, array[l]);
            ++total;
        }
        for (int i = l; i < length; ++i) {
            if (array[l] + array[i] > userLength)
                continue;

            if (array[l] + array[i] == userLength) {
                printf("%d = %d + %d\n", userLength, array[l], array[i]);
                ++total;
            }
            for (int j = i; j < length; ++j) {
                if (array[l] + array[i] + array[j] == userLength) {
                    printf("%d = %d + %d + %d\n",
                           userLength, array[j], array[l], array[i]);
                    ++total;
                }
            }
        }
    }
    return total;
}

如果你的数组非常大,并且你可以修改它或复制它,按递增顺序排序将减少比较次数,最后一个循环使用二进制搜索将节省时间复杂度从 O(N3) 降低到 O(N2 Log N)

关于C - 子集之和,需要更快的算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40915229/

相关文章:

c - 开关不自动断开是故意的?

c++ - char\0 转义序列 - 这是什么意思?

algorithm - 存储快速查询范围的最佳数据结构是什么?

python - 打印任意数量的 float

algorithm - 应该使用哪种排序算法在 O(n) 中运行?

c - 罗宾汉哈希在C

c - 使用具有 MFCC 功能的 kohonen 网络进行语音识别。如何设置神经元及其权重之间的距离?

java - 圆圈扇区内 child 的最大尺寸

algorithm - 回溯设计技术的通用定义

c - C 中除以零和未定义的行为