给定一个数字数组,是否将所有其他数字的乘积数组除以除法?

时间:2018-10-10 23:29:50

标签: java algorithm

最近有人通过电话问我以下面试问题:

  

给出一个整数数组,产生一个其值为   除当前索引外,其他所有整数的乘积。

     

示例:

     

[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)的复杂度做到这一点而无需除法吗?如果使用简单的原始整数数组,还有任何降低空间复杂性的方法。

2 个答案:

答案 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]
  • 因此,对每个元素1result/2arr[i]进行二进制搜索,以获得quotient,这是每个arr [i]的答案。

  • 时间复杂度:O(n *(log(n)),空间复杂度:O(1)。