有效地将数组的(n-1)个元素相乘
Posted
技术标签:
【中文标题】有效地将数组的(n-1)个元素相乘【英文标题】:Efficiently multiply (n-1) elements of an array [duplicate] 【发布时间】:2012-08-26 11:52:00 【问题描述】:可能重复:Interview Q: given an array of numbers, return array of products of all other numbers (no division)
我有两个数组 inputArray
和 resultArray
每个都有 n
元素。
任务是resultArray
中的第 n 个元素应该与 inputArray
中的所有元素相乘,inputArray
中的第 n 个元素除外(n-1
元素中的所有元素)。
例如。 inputArray=1,2,3,4
然后resultArray=24,12,8,6
这很容易......
for(i = 0; i < n; i++)
for(j = 0; j < n; j++)
if(i != j) resultArray[i] *= inputArray[j];
但问题是复杂度不应超过 O(n) 我们也不允许使用除法。 我该如何解决?
【问题讨论】:
和log10 (inputArray[i])
相加算作弊,然后做resultArray[i] = pow(10., sum - log10(inputArray[i]))
?
如果你能把这个问题转化为除法就很简单了。如果将结果视为除法而不是乘法的结果,结果中的第 i 个元素是什么?
【参考方案1】:
不要过多破坏,您应该尝试使用两个变量来存储乘法的结果:第 i 个元素左侧和第 i 个元素右侧的乘法的累积结果。
【讨论】:
你告诉他标准的方式..为什么不让他用很酷的方式呢? 这种方式比试图找到模 2^32 的乘法逆元要快得多(即使它具有相同的整体算法复杂度) @ronalchn 但它并不酷,唯一的要求是应该是 O(n),而不是尽可能快 在编程比赛中,您希望得到能够尽可能快地编码的解决方案,编程时间和运行时间都很宝贵 @ronalchn 这不是问题所说的。此外,找到乘法逆元并没有那么慢。只需少量乘法。【参考方案2】:您可以使用 DP 方法,如下所示:
vector<int> products(const vector<int>& input)
int N = input.size();
vector<int> partial(N+1); // partial[i] = input[0]...input[i-1]. partial[0] = 1
partial[0] = 1;
for (int i = 0; i < N; ++i) partial[i+1] = input[i]*partial[i];
vector<int> ans(N);
int current = 1;
for (int i = N-1; i >= 0; --i)
// current is equal to input[i+1]...input[N-1]
ans[i] = partial[i]*current;
current *= input[i];
return ans;
这种方法的一种可能用法是当您处理无法除的事物时(例如,考虑与矩阵相同的问题)。
我使用 STL 向量完成了这个解决方案,但当然可以轻松“翻译”代码以使用 C 数组。
【讨论】:
我才发现这其实和Ben Rujil很像,没有分界线。不错。 DP 的意图是双通道(即双通道,DP)。作业的重要部分是 O(N) 不一定意味着单程;任何固定数量的通行证(在这种情况下为 2 个)都符合 O(N)。【参考方案3】:您是否知道乘以奇数是可逆的 - 仅使用乘法?请参阅 Hacker's Delight,称为“精确除法”。正如那里解释的那样,这个技巧也可以扩展到偶数。因此,您可以通过几次乘法“除”第 n 个数字 - 由于这是家庭作业,我将由您自己了解如何操作。
【讨论】:
【参考方案4】:main()
int i,l,r,x[5]=1,2,3,4,5,y[5]; // x is the initial array, y is the final array
int n = 5; // n be the size of the array, here already defined as 5
l = 1; // l is the product of the values of the left side of an index in x
r = 1; // r is the product of the values of the right side of an index in x
for (i=0 ; i<5 ; i++) y[i]=1; // initialising all y values to 1
for (i=0 ; i<5 ; i++)
y[i] = y[i]*l ;
y[n-i-1] = y[n-i-1]*r;
l = l*x[i];
r = r*x[n-i-1];
for (i=0; i<5; i++) printf("%d\n",y[i]);
【讨论】:
【参考方案5】:看到 Daniel Fleischman 的回答,我决定我必须给出自己的实现,因为他的代码行数太多了!
int i, buffer=1, result[n];
for(result[0]=1,i=1;i<n;i++) result[i] = result[i-1]*inputArray[i-1];
for(i=n-1,buffer=1;i>=0;buffer*=inputArray[i],i--) result[i]*=buffer;
三行代码(去掉所有的肥肉)。
http://ideone.com/EaQiu
【讨论】:
我不知道OP正在为ioccc做作业.. 这不是关于 LOC 而是关于可读性 可读性更多地依赖于函数的良好命名和文档,而不是让简单的函数占用多行代码。 它被标记为作业,所以实际上代码并不受欢迎。以上是关于有效地将数组的(n-1)个元素相乘的主要内容,如果未能解决你的问题,请参考以下文章