2013 腾讯实习生笔试题
题目:给定一个数组a[N],我们希望构造数组b[N],其中b[i]=a[0]*a[1]*...*a[N-1]/a[i]。
在构造过程:不允许使用除法;
要求:O(1)空间复杂度和O(n)时间复杂度;
除遍历计数器与a[N] b[N]外,不可使用新的变量(包括栈临时变量、对空间和全局静态变量等);
请用程序实现并简单描述。
解法1:
不能使用新的变量,利用收尾元素作为中间变量,第一次迭代b[0] = a[0], for (i 1->n-1) b[i] = b[0],b[0] *= a[i]。
使b[] = {1, a[0],a[0]*a[1],...,a[0]*a[1]*a[2]*...*a[i-1]},第二次迭代 b[0] = 1, for (i n-1->1) b[i] *= b[0],
b[0] *= b[i];得到b数组。
代码:
//解法1 class Solution { public: /** * @param A: Given an integers array A * @return: A long long array B and B[i]= A[0] * ... * A[i-1] * A[i+1] * ... * A[n-1] */ vector<long long> productExcludeItself(vector<int> &a) { // write your code here vector<long long> b; b.resize(a.size()); b[0] = a[0]; int num = a.size(); for (int i=1; i<num; ++i) { b[i] = b[0]; /// 1 a[0...i-1] b[0] *= a[i]; } b[0] = 1; for (int i=num-1; i>0; --i) { b[i] *= b[0]; b[0] *= a[i]; } return b; } };
解法2:
三次循环,第一次,b[0] = 1, for (int i=1; i<num; ++i) b[i] = b[i-1] * a[i-1];使b[] = {1, a[0], ...,a[0]*...*a[i-1]...}
第二次,a[n-1] = a[n-2], a[n-2] = a[n-1](异或实现交换), for (int i=n-3; i>=0; --i) a[n-1] *= a[i+1], a[i] = a[n-1], a[n-1] = a[i];
使a[] = {a[1]*...*a[n-1],.... , a[n-1]*a[n-2]*...*a[i+1],...}.第三次循环使b[i] *= a[i].
附代码:
//解法2 class Solution { public: /** * @param A: Given an integers array A * @return: A long long array B and B[i]= A[0] * ... * A[i-1] * A[i+1] * ... * A[n-1] */ vector<long long> productExcludeItself(vector<long long> &a) { // write your code here vector<long long> b; b.resize(a.size()); int num = a.size(); b[0] = 1; for (int i=1; i<num; ++i) { b[i] = b[i-1] * a[i-1]; // b[i] = a[0...i-1] } a[num-2] = a[num-1] ^ a[num-2]; a[num-1] = a[num-2] ^ a[num-1]; a[num-2] = a[num-2] ^ a[num-1]; for (int i=num-3; i>=0; --i) { // a[i] = a[num-1...i+1] a[num-1] *= a[i+1]; a[i] = a[num-1] ^ a[i]; a[num-1] = a[i] ^ a[num-1]; a[i] = a[i] ^ a[num-1]; } a[num-1] = 1; for (int i=0; i<num; ++i) { b[i] *= a[i]; } return b; } };
解法2要求a数组也是long long 型。
参考链接:http://www.cnblogs.com/sooner/archive/2013/04/22/3036448.html