题目描述:
给定一个数组A[0,1,…,n-1],请构建一个数组B[0,1,…,n-1],其中B中的元B[i]=A[0]A[1]…*A[i-1]A[i+1]…*A[n-1]。不能使用除法。
思路分析:
数组B每个位置的值就是数组A中除了同一位置上的那个数,数组中剩下的数的累积。一开始我想到的思路是先求出A数组中所有数的累积,然后再除以A[i]即可获得B[i]的值。但是题干中明确要求不能使用除法,所以此法作罢。
这时候又很快想到简单粗暴的暴力递归的方法,直接遍历两个for循环嵌套。时间复杂度为O(N^2)
代码实现如下:
1.暴力递归
public class Solution {
public int[] multiply(int[] A) {
if(A == null || A.length< 1){
return A;
}
int length = A.length;
int[] B = new int[length];
for(int i = 0 ; i < length ; i++){
B[i] = 1;
for(int j = 0 ; j < length; j++){
if(i==j){
continue;
}
B[i] = B[i]*A[j];
}
}
return B;
}
}
显然暴力递归虽然思想简单,但是时间复杂度过高,所以这肯定不是本题的考察重点。开始时没想到动态递归这种思路,还是看了牛客网后面的大家讨论才明白的,将该位置的左右两边的乘积分别存入新数组中,然后对应位置相乘即可。
左边的值是自上而下的三角,每一层左边的乘积都等于上一层的乘积再乘以A(i-1)的值,右边同理。
2.动态递归:
代码实现如下:
//考察动态规划的题
import java.util.ArrayList;
public class Solution {
public int[] multiply(int[] A) {
if(A == null || A.length< 1){
return A;
}
int length = A.length;
int[] B = new int[length];
int[] left = new int[length];//记录左边的乘积
int[] right = new int[length];//记录右边的乘积
left[0] = right[length-1] = 1;
for(int i = 1 ; i < length ; i++){
left[i] = left[i-1]*A[i-1];
}
for(int i = length-2 ; i>=0 ; i--){
right[i] = right[i+1]*A[i+1];
}
for(int i = 0 ; i<length ; i++){
B[i] = right[i]*left[i];
}
return B;
}
}