剑指Offer - 构建乘积数组(Java实现)

题目描述:

给定一个数组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;
    }
}

猜你喜欢

转载自blog.csdn.net/justlikeu777/article/details/86419934