劍指Offer - 構建乘積陣列(Java實現)
阿新 • • 發佈:2019-01-13
題目描述:
給定一個數組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; } }