1. 程式人生 > 實用技巧 >劍指Offer_#66_構建乘積陣列

劍指Offer_#66_構建乘積陣列

劍指Offer_#66_構建乘積陣列

劍指offer

Contents

題目

給定一個數組 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]。不能使用除法。

示例:
輸入: [1,2,3,4,5]
輸出: [120,60,40,30,24]

提示:
所有元素乘積之和不會溢位 32 位整數
a.length <= 100000

思路分析

用除法的解法

本題難點在於題目限制不準用除法,如果可以用除法的話,很好解決。

  • 計算A[]中所有元素乘積product
  • 遍歷一遍A[]陣列,B[i] = product / A[i]

不用除法的解法

將每個B[i]的表示式寫出來,就是下面表格的樣子。

我們發現可以每一行被1分為左右兩個部分,或者說上三角部分和下三角部分。
我們可以分別計算每一行當中1的左邊部分,1的右邊部分,然後將兩部分相乘,就得到對應的B[i]
編碼技巧: 計算上下三角部分的乘積時,非常容易弄錯,最好先在紙上畫出上述表格,然後對照著寫,不然容易亂。

解答

解答1:較直觀的寫法

這個程式碼比較直觀,可讀性好,但是空間複雜度稍高,藉助2個額外的陣列。空間複雜度為O(n)。

class Solution {
    public int[] constructArr(int[] a) {
        int n = a.length;
        if(n == 0) return new int[0];
        int[] up = new int[n];//上三角部分乘積
        int[] down = new int[n];//下三角部分乘積
        //上三角從最下邊的1開始迭代
        up[n - 1] = 1;
        //下三角從最上邊的1開始迭代
        down[0] = 1;
        //計算上三角部分,由下到上累乘
for(int i = n - 2;i >= 0;i--){ up[i] = up[i + 1] * a[i + 1]; } //計算下三角部分,由上到下累乘 for(int i = 1; i <= n - 1;i++){ down[i] = down[i - 1] * a[i - 1]; } //最後將上下三角部分逐位對應相乘,得到的新陣列就是結果B[0...n-1] for(int i = 0;i <= n - 1;i++){ up[i] *= down[i]; } return up; } }

複雜度分析

時間複雜度: O(n)
空間複雜度: O(n)

解答2:優化空間複雜度

少用了一個數組,可讀性稍微差點。因為b是返回值,所以不算在空間複雜度內。

class Solution {
    public int[] constructArr(int[] a) {
        if(a.length == 0) return new int[0];
        int[] b = new int[a.length];
        b[0] = 1; 
        //將上三角中的數字乘入b[i]
        for(int i = 1; i <= b.length - 1;i++){
            b[i] = b[i - 1] * a[i - 1];
        }
        //將下三角中一行的數字相乘,記作tmp,然後乘入b[i]
        int tmp = 1;
        for(int i = a.length - 2;i >= 0;i--){
            tmp *= a[i + 1];
            b[i] *= tmp;
        }
        return b;
    }
}

複雜度分析

時間複雜度: O(n)
空間複雜度: O(1)