No.238 LeetCode題目 “除自身以外數組的乘積”

題目描述

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

示例:

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

提示:題目數據保證數組之中任意元素的全部前綴元素和後綴(甚至是整個數組)的乘積都在 32 位整數範圍內。

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

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

解題思路

題目要求時間複雜度爲O(n),因此不能用多重循環的方法解題。
題目要求不能用除法,因此不能用最終乘積除以每一個元素。

因此我們可以考慮最終結果爲該數左側的累積乘以該數右邊的累積

output[i] = left[i] * right[i]

一、空間複雜度O(n)

定義兩個數組left[]right[]分爲記錄左側的累積和右側的累積,如下圖所示:(圖源LeetCode官方)
在這裏插入圖片描述
在這裏插入圖片描述
最後的結果利用output[i] = left[i] * right[i]即可。

二、空間複雜度O(1)

由於題目要求,output數組不佔用空間,因此只用output數組即可。

第一遍遍歷,讓output數組中元素爲左側數字的累積。
第二遍遍歷,讓output直接賦值爲結果即可。

除此之外,還需要一個變量right在第二遍遍歷時記錄右側的累積。

具體實現細節請見代碼及註釋。

具體代碼

一、 空間複雜度O(n)

class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {
      //定義輸出數組
      vector<int>output;
      //計算數組長度
      int length = nums.size();
      int left[length];//存放左邊整數乘積
      int right[length];//存放右邊整數乘積
      //邊緣元素初始化爲1
      left[0] = 1;
      right[length - 1] = 1;
      //爲左邊的整數乘積賦值
      for(int i = 1;i<length;i++){
        left[i] = left[i-1] * nums[i-1];
      }
      //爲右邊的整數乘積賦值
      for(int i = length - 2;i>=0;i--){
        right[i] = right[i+1] * nums[i+1];
      }
      //爲輸出output賦值
      for(int i =0;i<length;i++){
        output.push_back(left[i] * right[i]);
      }
      return output;
    }
};

二、空間複雜度O(1)

class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {
      //計算數組長度
      int length = nums.size();
      //定義輸出數組,且只用這一個數組
      vector<int>output(length);
      //初始化最左邊的整數乘積爲1
      output[0] = 1;
      //爲左邊的整數乘積賦值
      for(int i = 1;i<length;i++){
        output[i] = output[i-1] * nums[i-1];
      }
      //利用一個變量記錄右邊整數乘積
      int right = 1;   
      //爲output賦值
      for(int i = length - 1;i>=0;i--){
        output[i] *= right;
        right *= nums[i];
      }
      return output;
    }
};

性能結果

一、 空間複雜度O(n)
在這裏插入圖片描述

二、空間複雜度O(1)

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章