算法介绍
求对于长度为N的数组A,求子数组的和接近0的子数组。
例如:
求取算法介绍
定义n长度的空间sum[0…N-1],sum[i]是A的前i项和。
并且有sum[i+1]=sum[i]+A[i+1]。
首先对sum[i]进行排序,找到求和最接近的2个值。
同时记录使得值最小的数组最短的那一组。
如图:
通过求取求和值最接近的一组数据可以找到零子数组对应的位置,之后判断是否是最短,即可求出最终零子数组的具体对应位置。
算法详解
第一步:逐位求和
第二步:对求和排序
第三步:寻找排序后相邻差最小值
第四步:记录位置
由于本文采用的是分治法排序,因此算法复杂度为O(NlogN)
void devide(int *A, int n) {
int *sum;
int *original;
int firstPos = 0;
int secondPos = 0;
// 用于记录sum相减的第一个值
int firstNum = 0;
// 用于记录sum相减的第二个值
int secondNum = 0;
// 创建求和数组用于排序
sum = (int*)malloc(sizeof(int)*n);
// 用于存储原始求和数组,用以判断零子数组位置
original = (int*)malloc(sizeof(int)*n);
// 求取具体求和值
for (int i = 0; i < n; i++) {
sum[i]=A[i];
}
sum[0] = A[0];
for (int i = 1; i < n; i++) {
sum[i] = sum[i - 1] + A[i];
}
// 将求和值存储下来
for (int i = 0; i < n; i++) {
original[i] = sum[i];
}
// 进行排序,排序算法在后面给出,应用的是分治法
sort(sum, 0, n - 1);
// 定义sum排序后相邻值相减后的最小值
int *min;
int *originalMin;
min = (int*)malloc(sizeof(int)*(n - 1));
originalMin = (int*)malloc(sizeof(int)*(n - 1));
min[0] = sum[1] - sum[0];
for (int i = 2; i < n; i++) {
min[i-1] = sum[i] - sum[i - 1];
}
// 记录使得sum相减最小时两个用来相减值得具体数据
int less = min[0];
for (int i = 0; i < n - 1; i++) {
if (less > min[i]) {
less = min[i];
firstNum = sum[i];
secondNum = sum[i + 1];
}
}
// 获取零子数组的起始坐标
for (int i = 0; i < n; i++) {
if (original[i] == firstNum) {
firstPos = i;
break;
}
}
// 获取零子数组的终止坐标
for (int i = 0; i < n; i++) {
if (i != firstPos && original[i] == secondNum) {
secondPos = i;
break;
}
}
// 打印零子数组
for (int i = firstPos + 1; i < secondPos + 1; i++) {
printf("A[%d]=%d\n", i, A[i]);
}
}
分治排序法:
void sort(int *A, int from, int to) {
if (from < to) {
int mid = (from + to) / 2;
//对半分解
sort(A, from, mid);
sort(A, mid + 1, to);
// 合并
merge(A, from, mid, to);
}
}
合并算法:
void merge(int *A, int from, int mid, int to) {
int i = from;
int j = mid + 1;
int t = 0;
int *tmp = (int*)malloc(sizeof(int)*(8));
while (i <= mid && j <= to) {
if (A[i] <= A[j]) {
tmp[t++] = A[i++];
}
else {
tmp[t++] = A[j++];
}
}
while (i <= mid) {
tmp[t++] = A[i++];
}
while (j <= to) {
tmp[t++] = A[j++];
}
t = 0;
while (from <= to) {
A[from++] = tmp[t++];
}
}
参考资料: