1. 程式人生 > 其它 >LeetCode-238 除自身以外陣列的乘積

LeetCode-238 除自身以外陣列的乘積

題目來源

LeetCode-238 除自身以外陣列的乘積

題目描述

給你一個長度為n的整數陣列nums,其中n > 1,返回輸出陣列output,其中 output[i]等於nums中除nums[i]之外其餘各元素的乘積。

示例:

輸入: [1,2,3,4]
輸出: [24,12,8,6]

提示: 題目資料保證陣列之中任意元素的全部字首元素和字尾(甚至是整個陣列)的乘積都在 32 位整數範圍內。

說明:不要使用除法,且在O(n) 時間複雜度內完成此題。

進階:
你可以在常數空間複雜度內完成這個題目嗎?( 出於對空間複雜度分析的目的,輸出陣列不被視為額外空間。)

題解分析

複雜度O(n)+空間複雜度O(n)解法

解法一

  1. 從本題的題目可以分析,結果陣列中,每一個位置的結果是原始陣列前半部分和後半部分的乘積。
  2. 所以,可以分別增加兩個陣列分別儲存字首陣列和字尾陣列的積。
class Solution {
    public int[] productExceptSelf(int[] nums) {
        int n = nums.length;
        int[] pre = new int[n], last = new int[n];
        pre[0] = 1;
        for(int i = 1; i < n; i++){
            pre[i] =pre[i-1] * nums[i-1];
        }
        last[n-1] = 1;
        for(int i = n-2; i >=0; i--){
            last[i] = last[i+1] * nums[i+1];
        }
        int[] result = new int[n];
        for(int i = 0; i < n; i++){
            result[i] = pre[i] * last[i];
        }
        return result;
    }
}

解法二

  1. 仔細檢查上述程式碼,可以發現我們的last陣列其實是多餘的,可以將result陣列和last陣列混合使用。
  2. 通過減少一個數組,也減少了記憶體消耗。
class Solution {
    public int[] productExceptSelf(int[] nums) {
        int n = nums.length;
        int[] pre = new int[n], last = new int[n];
        pre[0] = 1;
        for(int i = 1; i < n; i++){
            pre[i] =pre[i-1] * nums[i-1];
        }
        last[n-1] = 1;
        for(int i = n-2; i >=0; i--){
            last[i] = last[i+1] * nums[i+1];
        }
        for(int i = 0; i < n; i++){
            last[i] = pre[i] * last[i];
        }
        return last;
    }
}

時間複雜度O(n)+空間複雜度O(1)解法

  1. 再仔細檢視解法二的演算法,其實還可以發現一個更優的解法。
  2. 因為pre字首陣列是前向遍歷的,而且我們的result陣列計算也是前向遍歷的,那這兩個步驟是不是可以結合起來呢?
  3. 這其實是行得通的,我們可以通過設定一個字首積變數來累積字首,在構造result結果陣列時,只需要將字首積變數和last也即result陣列相乘即可。
class Solution {
    public int[] productExceptSelf(int[] nums) {
        int n = nums.length;
        int[] result = new int[n];
        int pre = 1;
        result[n-1] = 1;
        for(int i = n-2; i >=0; i--){
            result[i] = result[i+1] * nums[i+1];
        }
        for(int i = 1; i < n; i++){
            pre = pre * nums[i-1];
            result[i] = pre * result[i];
        }
        return result;
    }
}
Either Excellent or Rusty