Product of Array Except Self

来源:互联网 发布:mac上怎么用office 编辑:程序博客网 时间:2024/05/17 04:45


Given an array of n integers where n > 1, nums, return an array output such that output[i] is equal to the product of all the elements of nums except nums[i].

Solve it without division and in O(n).

For example, given [1,2,3,4], return [24,12,8,6].

特殊情况
数组指针为空,数组长度为0,数组长度为1,代码中对这些情况,都直接返回传入的数组指针
数组成员包含整数0,非常重要的特殊条件
数组成员相乘以后的数值范围,是否会超出int范围
数组成员是否会有负数,这里正负没有影响,只是大小不要溢出了

测试用例
排除特殊情况以后,就没有什么特别的了,可以直接使用例题中的数据测试

解题思路
有多种解法
1. 暴力计算,时间复杂度O(n^2)效率太差。但是可以给出一些启发
2. 保留所有数相乘以后的总积,然后除以各个对应的数组成员即可,时间复杂度O(n)。 貌似很巧妙地解法,但是需要考虑总积溢出,数组成员为0的情况。例外情况的处理比较复杂。
3. 由于乘积不需要包含本项,所以可以使用两个数组,一个包含左侧乘积,另外一个包含右侧乘积,最后两者相乘取结果即可。空间复杂度O(n),时间复杂度O(n)。溢出的可能性稍微小一些,但是不需要考虑除零的问题了。代码比较直白,易懂。
4. 在3的基础上,先利用输出数组保留右侧乘积,再一边计算左侧乘积,一边覆盖输出数组。通过这样的改进,空间复杂度降为O(1)。输出数组不作为空间复杂度计算

C代码,方法3

int* poa(int* a, int n) {   if (a==NULL) return a;   if (n<=1) return a;      int* res = (int*)malloc(n * sizeof(int));   int* left = (int*)malloc(n * sizeof(int));   int* right = (int*)malloc(n * sizeof(int));   for (int i=0; i<n; i++) left[i] = right[i] = 1;   for (int i=1; i<n; i++) left[i] = left[i-1] * a[i-1];   for (int i=n-2; i>=0; i--) right[i] = right[i+1] * a[i+1];   for (int i=0; i<n; i++) res[i] = left[i] * right[i];   free(left);   free(right);      return res;}


C++代码,方法3

void poa(int a[], int n, int out[]) {   if (a == NULL || n <= 1) return;   // assume out is always valid      int* left = new int[n];   int* right = new int[n];   for (int i=0; i<n; i++) left[i] = right[i] = 1;   for (int i=1; i<n; i++) left[i] = left[i-1] * a[i-1];   for (int i=n-2; i>=0; i--) right[i] = right[i+1] * a[i+1];   for (int i=0; i<n; i++) out[i] = left[i] * right[i];   delete[] left;   delete[] right;}


C++代码,方法3,用向量

#include <iostream>#include <vector>using namespace std;void poa(vector<int>& a, vector<int>& out) {   int n = a.size();   if (n < 1) return;   // a.size() == 1, return [1]   // assume out is always valid      vector<int> left(n, 1), right(n, 1); //注意是用圆括号初始化数组大小   for (int i=1; i<n; i++) left[i] = left[i-1] * a[i-1];   for (int i=n-2; i>=0; i--) right[i] = right[i+1] * a[i+1];   for (int i=0; i<n; i++) out[i] = left[i] * right[i];}int main(int argc, char * argv[]){   int a[] = {3,4,2,5};   int n = sizeof(a)/sizeof(int);   vector<int> in(a, a+n);   vector<int> out(n);   poa(in, out);   for (int i=0; i<n; i++) cout << in[i] << " ";   cout << endl;   for (int i=0; i<n; i++) cout << out[i] << " ";   cout << endl;   return 0;}


C++代码,方法4,看上去代码更简单

void poa(int a[], int n, int out[]) {if (a==NULL || n<=1) return;// assume out is always validout[n-1] = 1;for (int i=n-2; i>=0; i--) out[i] = out[i+1] * a[i+1];int left = 1;for (int i=1; i<n; i++) {left *= a[i-1]; // 这里注意顺序,容易出错,可以参考之前模拟计算时的顺序out[i] *= left;}}


0 0