有一个整数数组,比方说3,5,7,9。您应该创建另一个数组并填充它,使得第二个数组的第0个位置应该是第一个数组中所有数字的乘积,不包括第0个位置的数字,这意味着它应该是5x7x9(不包括3),索引处的数字第二个数组中的1个将是3x7x9(不包括5)的乘积。
我想到的第一个答案是有两个for循环,这将导致O(n2)的时间复杂度。后来我想到了这个:
将第一个数组中的所有数字相乘(3x5x7x9),并在填充第二个数组时,我将该产品除以该位置的数字。如果我填充第0个位置则除以3,如果我填充第1个位置则除以5,依此类推。这会降低从O(n2)到O(2n)的复杂性。
但是面试官说不允许分裂。除了在某种数据结构中存储不同的可能倍数并在填充时使用它,我想不出别的。我放弃了,但当被问到答案时,他说他会保留2个向前和向后的多重阵列。当被问及解决方案的空间复杂性问题时,他说可以对其进行优化。
答案 0 :(得分:8)
我不确定问题是关于空间还是解决方案本身。由于每个人都提供解决方案,这让我觉得他们不理解面试官的解决方案,所以这里有一个解释:
我们维护两个阵列。第一个是原始数组的运行产品。因此,i
处的元素将是原始数组中第一个i
元素的乘积(没有乳胶,但i
th 条目具有值pi{j=0 to i} j
)。第二个数组只是反方向,因此i
th 条目的值为pi{j=N-i to N} j
。
要构造所需的最终数组,我们只需运行两个数组中的每一个并乘以条目。因此,最终数组中的i
th 值将是所有条目的乘积,这是0
到i-1
次乘积的乘积。 i+1
到N
,它是第一个数组的i-1
条目和第二个数组的i+1
条目的乘积。
总时间和空间O(n)
答案 1 :(得分:3)
将元素1到i的产品存储到数组
A
中,A[i]
是元素1到元素i的产物;将元素i到n(输入大小)的产品存储到数组中
B
,B[i]
是元素i与元素n的乘积;- 醇>
当需要result [i]时,使用A [i-1] * B [i + 1]。角落案件是 这样简单,只需使用B [1]和A [n-2](A [n-1]是最后一个 元素)。
答案 2 :(得分:2)
我想我可以在O(n log n)中完成。
存储数字前半部分和数字后半部分的乘积。
还存储第一季度,第二季度,第三季度和第四季度的产品。
还存储第八,第二,第八,......第八十八的产品。
等等。
您可以通过计算每对产品,然后是每个那些对的产品,从而从头开始构建它,依此类推。
此处的额外数据总量为O(n),需要O(n)来计算(易于显示)。
现在,要计算(比如)元素0的输出,你可以得到下半年的产品,第二季度的产品(即第一季度的下半年),下半年的产品第八个等等,并将它们相乘。有这样的数字,所以这个操作是log n。
要计算元素k的乘积,请以二进制形式写入k并翻转其位。然后高位告诉你哪一半开始;下一位告诉你接下来要使用剩余一半的哪一半;下一位告诉你接下来要使用的剩余季度的哪一半;等等。
因此任何输出元素都可以在log n时间内计算出来。对n个输出元素中的每一个执行此操作,然后得到O(n log n)。
[编辑]
当然,“向前和向后的倍数”方法也有效。我猜我应该更仔细地阅读这个问题。 : - )
[编辑2]
至于面试官(和davin)的解决方案,你实际上并不需要构建一个额外的数组......假设你可以编辑输出数组中的值。
首先,构造输出数组B,使得B [i] = A [0] A [1] ... * A [i-1]且B [0] = 1。您可以逐步执行此操作,因此这是线性时间:
B[0] = 1;
for (i=1 ; i < n ; ++i) {
B[i] = B[i-1] * A[i];
}
接下来,从n-2扫描向后以计算答案,跟踪“到目前为止的产品”:
x = A[n-1];
for (j=n-2 ; j >= 0 ; ++j) {
B[j] *= x;
x *= A[j];
}
这解决了O(n)中的问题,而没有构建额外的数组。
答案 3 :(得分:1)
我相信他的意思是,给定一个数组A = {a_1,...,a_n},他会创建两个新数组:
F_A = {a_1,a_1 * a_2,...,a_1 * ... * a_n}
可以通过在数组上向前迭代时保持累积乘积来构建线性时间,
B_A = {a_1 * ... * a_n,...,a_n * a_(n-1),a_n}
可以通过维持累积乘积而在线性时间内构建,同时在数组上反向迭代。
现在,要在结果数组中填充索引i,只需将F_A [i-1]与B_A [i + 1]相乘:
F_A [i-1] * B_A [i + 1] = [a_1 * ... * a_(i-1)] * [a_(i + 1)* ... * a_n]
答案 4 :(得分:1)
滥用对数怎么样?而不是划分你减去?
但是如果你可以修改第一个数组,你可以做类似的事情
//pop arr2
r=1
for(i=len-1;i>=0;i--)
{
r=r*arr1[i]
arr2[i]=r
}
//modify arr1
r=1
for(i=0;i<len;i++)
{
r=r*arr1[i]
arr1[i]=r
}
//fix arr2
arr2[0]=arr2[1];
for(i=1;i<len-1;i--)
{
arr2[i]=arr2[i+1]*arr1[i-1];
}
arr2[len-1]=arr1[len-2];