免责声明:这是一个任务。我不要求明确的代码,只需要足够的帮助来理解所涉及的算法,以便我可以修复代码中的错误。
好的,所以您可能熟悉最大子数组问题:计算并返回数组中最大的连续整数块。很简单,但这个任务需要我以三种不同的复杂度来完成:O(n^3)、O(n^2) 和 O(n log n)。我已经得到了前两个没有太多麻烦(蛮力),但第三个让我头疼......从字面上看。
我了解该算法应该如何工作:一个数组被传递给一个函数,该函数递归地将其分成两半,然后比较各个组件以找到每一半的最大子数组。然后,因为最大子数组必须完全位于左半部分或右半部分,或者位于与两者重叠的段中,所以您必须找到与左右重叠的最大子数组。比较每种情况的最大子数组,最大的将是您的返回值。
我相信我已经编写了能够充分执行该任务的代码,但我的评估似乎是错误的。我一直在尝试联系导师和助教寻求帮助,但我觉得他们中的任何一个都没有取得任何进展。以下是我迄今为止设法编写的代码。如果您发现任何明显的错误,请告诉我。同样,我不是在寻找明确的代码或答案,而是帮助理解我做错了什么。我浏览了这里介绍的所有类似案例,但没有发现任何可以真正帮助我的东西。我也做了很多谷歌搜索以寻求指导,但这也无济于事。无论如何,这是有问题的代码:
int conquer(int arr[], int first, int mid, int last) {
int i = 0;
int maxLeft = 0;
int maxRight = 0;
int temp = 0;
for (i = mid; i >= first; i--) {
temp = temp + arr[i];
if (maxLeft < temp) {
maxLeft = temp;
}
}
temp = 0;
for (i = (mid + 1); i <= last; i++) {
temp = temp + arr[i];
if (maxRight < temp) {
maxRight = temp;
}
}
return (maxLeft + maxRight);
}
int divide(int arr[], int start, int end) {
int i;
int maxSum;
int maxLeftSum;
int maxRightSum;
int maxOverlapSum;
if (start == end) {
return arr[start];
} else {
int first = start;
int mid = (end / 2);
int last = end;
maxSum = 0;
maxLeftSum = 0;
for (i = first; i < mid; i++) {
maxSum = maxSum + arr[i];
if (maxLeftSum < maxSum) {
maxLeftSum = maxSum;
}
}
for (i = (mid + 1); i < last; i++) {
maxSum = maxSum + arr[i];
if (maxRightSum < maxSum) {
maxRightSum = maxSum;
}
}
maxOverlapSum = conquer(arr, first, mid, last);
}
if ((maxLeftSum > maxRightSum) && (maxLeftSum > maxOverlapSum)) {
return maxLeftSum;
} else if ((maxRightSum > maxLeftSum) && (maxRightSum > maxOverlapSum)) {
return maxRightSum;
} else
return maxOverlapSum;
}
编辑:我得到的错误是不正确的结果。我的其他两种算法之间的结果一致且正确,但这个不正确。
编辑#2:这是我的代码的更新版本,精简了一点,我修复了一些东西。它仍然没有正确运行,但它应该更接近......
#include <stdio.h>
#include <stdlib.h>
int numarr[] = {22, -27, 38, -34, 49, 40, 13, -44, -13, 28, 46, 7, -26, 42,
29, 0, -6, 35, 23, -37, 10, 12, -2, 18, -12, -49, -10, 37, -5, 17,
6, -11, -22, -17, -50, -40, 44, 14, -41, 19, -15, 45, -23, 48, -1,
-39, -46, 15, 3, -32, -29, -48, -19, 27, -33, -8, 11, 21, -43, 24,
5, 34, -36, -9, 16, -31, -7, -24, -47, -14, -16, -18, 39, -30, 33,
-45, -38, 41, -3, 4, -25, 20, -35, 32, 26, 47, 2, -4, 8, 9, 31, -28,
36, 1, -21, 30, 43, 25, -20, -42};
int length = ((sizeof(numarr))/(sizeof(int)));
int divide(int left, int right) {
int mid, i, temp, mLeft, mRight, mCross = 0;
if (left == right) {
return left;
} else if (left > right) {
return 0;
} else {
mid = (left + right) / 2;
divide(left, mid);
divide(mid + 1, right);
for (i = mid; i >= left; i--) {
temp = temp + numarr[i];
if (mLeft < temp) {
mLeft = temp;
}
}
for (i = mid + 1; i <= right; i++) {
temp = temp + numarr[i];
if (mRight < temp) {
mRight = temp;
}
}
mCross = (mLeft + mRight);
printf("mLeft: %d\n", mLeft);
printf("mRight: %d\n", mRight);
printf("mCross: %d\n", mCross);
return 0;
}
}
int main(int argc, char const *argv[])
{
divide(0, length);
return 0;
}