连续子数组的最大乘积
- 给定一个长度为N的整数数组,只允许用乘法,不能用除法,计算任意(N-1)个数的组合乘积中最大的一组,并写出算法的时间复杂度。(附加:除遍历计数器与a[N] b[N]外,不可使用新的变量,包括栈临时变量、堆空间和全局静态变量等);
- 有一个整数数组,求出连续子数组的和的绝对值的最小值。
1、思路:
先从前往后: B[0]=1, B[1]=A[0], B[2]=A[0]×A[1]...
再从后往前: temp = 1, temp *= A[n], B[n - 1] *= temp. 就得到除去n-1个数以外,其他数的乘积。
时间复杂度O(n),空间复杂度O(1),符合题目要求。
1 int MaxMultiply(const int* A, int len) 2 { 3 int* B = new int[len]; 4 B[0] = 1; 5 for (int i = 1; i < len; i++) 6 B[i] = B[i - 1] * A[i - 1]; 7 int temp = 1; 8 for (int j = len - 2; j >= 0; j--) 9 { 10 temp *= A[j + 1]; 11 B[j] *= temp; 12 } 13 int max = 0x80000000; 14 for (int k = 0; k < len; k++) 15 if (B[k] > max) max = B[k]; 16 delete[] B; 17 return max; 18 }
附加:用b[0]来代替temp。第二个循环换成如下:
1 for (i = MAXN - 1; i >= 1; i--) 2 { 3 b[i] *= b[0]; 4 b[0] *= a[i]; 5 }
2、思路:
对数组A[1...N],做和运算S[1...N],其中S[1] = A[1]; S[2] = A[1]+A[2];...;S[N]=A[1]+A[2]+A[3]+...+A[N]。然后对S[1...N]从小到大排序。最后连续子段绝对值最小:Min{ |S[i+1]-S[i]|} 1<=i<=N。
1 int MinDiffAbs(int data[], int length) 2 { 3 int* sums = new int[length]; 4 sums[0] = data[0]; 5 for (int j = 1; j < length; j++) 6 sums[j] = sums[j - 1] + data[j]; 7 sort(sums, sums + length); 8 PrintArray(sums, length); 9 int minDiff = 0x7FFFFFFF, diff; 10 for (int i = length - 1; i > 0; i--) 11 { 12 diff = abs(sums[i - 1] - sums[i]); 13 if (diff < minDiff) 14 minDiff = diff; 15 } 16 delete[] sums; 17 return minDiff; 18 }