最近有人通过电话问我以下面试问题:
给出一个整数数组,产生一个其值为 除当前索引外,其他所有整数的乘积。
示例:
[4、3、2、8]-> [3 * 2 * 8、4 * 2 * 8、4 * 3 * 8、4 * 3 * 2]-> [48、64、96、24]
我想出了以下代码:
public static BigInteger[] calcArray(int[] input) throws Exception {
if (input == null) {
throw new IllegalArgumentException("input is null");
}
BigInteger product = calculateProduct(input);
BigInteger result[] = new BigInteger[input.length];
for (int i = 0; i < input.length; i++) {
result[i] = product.divide(BigInteger.valueOf(input[i]));
}
return result;
}
private static BigInteger calculateProduct(int[] input) {
BigInteger result = BigInteger.ONE;
for (int i = 0; i < input.length; i++) {
result = result.multiply(BigInteger.valueOf(input[i]));
}
return result;
}
复杂度:
Time Complexity: O(n)
Space Complexity: O(n)
我们能以O(n)的复杂度做到这一点而无需除法吗?如果使用简单的原始整数数组,还有任何降低空间复杂性的方法。
答案 0 :(得分:2)
请考虑位于索引i
处的元素。向左看,可以说我们有一个元素乘积,直到索引i-1
。让我们称之为leftProduct[i]
,它是i
元素左侧所有元素的乘积。同样,让调用rightProduct[i]
是i
元素右边所有元素的乘积。
那么该索引的结果为output[i] = leftProduct[i]*rightProduct[i]
现在考虑如何获取leftProduct
。您只需从数组开始遍历并计算一个正在运行的产品,然后在每个元素处使用当前正在运行的产品更新leftProduct
。
同样,您可以通过从末尾遍历数组来计算rightProduct
。在这里,您可以通过乘以leftProduct
来更新rightProduct
数组来重用public static int[] getProductsExcludingCurrentIndex( int[] arr ) {
if ( arr == null || arr.length == 0 ) return new int[]{};
int[] leftProduct = new int[arr.length];
int runningProduct = 1;
//Compute left product at each i
for ( int i = 0; i < arr.length; i++ ) {
leftProduct[i] = runningProduct;
runningProduct = runningProduct*arr[i];
}
runningProduct = 1;
//By reverse traversal, we compute right product but at the same time update the left
//product, so it will have leftProduct*rightProduct
for ( int i = arr.length - 1; i >= 0; i-- ) {
leftProduct[i] = leftProduct[i]*runningProduct;
runningProduct = runningProduct*arr[i];
}
return leftProduct;
}
数组来优化空间。
下面的代码演示了这一点:
O(n)
空间复杂度为leftProduct
-我们仅使用一个数组O(n)
,时间复杂度为O(1)
。
但是如果您不考虑用于存储输出的空间,则为leftProduct
,因为我们将输出存储在public Step partiotionStep() {
return stepBuilderFactory.get("partiotionStep")
.partitioner("slaveStep", partitioner())
.step(new FlowStep(flow()))
.taskExecutor(taskExecutor())
.build();
public Flow flow() {
return new FlowBuilder<Flow>("flow")
.start(step1())
.next(step2())
.next(step3())
.build();
本身中。
如果您严格不希望有多余的空间,则需要修改输入数组。至少据我所知,根本无法通过修改输入数组来解决此问题。
答案 1 :(得分:0)
我的想法:
result
中。result / arr[i]
。因此,对每个元素1
从result/2
到arr[i]
进行二进制搜索,以获得quotient
,这是每个arr [i]的答案。
时间复杂度:O(n *(log(n)),空间复杂度:O(1)。