leetcode-238-product-of-array-except-self
題目
Given an integer array nums
, return an array answer
such that answer[i]
is equal to the product of all the elements of nums
except nums[i]
.
The product of any prefix or suffix of nums
is guaranteed to fit in a 32-bit integer.
You must write an algorithm that runs in O(n)
time and without using the division operation.
Example 1
1 | Input: nums = [1,2,3,4] |
Example 2
1 | Input: nums = [-1,1,0,-3,3] |
Constraints:
- 2 <= val <= 105
- -30 <= nums[i] <= 30
- The product of any prefix or suffix of
nums
is guaranteed to fit in a 32-bit integer.
Follow up:
Follow up: Can you solve the problem in O(1) extra space complexity? (The output array does not count as extra space for space complexity analysis.)
解釋題目
題目會給一個 array 叫 nums,假設是 nums = [1, 2, 3, 4]
,需要遍歷整個 array,遍歷到的數字輸出會是,除了自己以外的其他三個數字相乘。舉例來說,遍歷到 1 時,輸出會是 2 * 3 * 4;遍歷到 2 時,輸出會是 1 * 3 * 4。所以,最後輸出會是 [24, 12, 8, 6]
。這題還有另外的限制是不能使用除法,且時間複雜度必須是 O(n)。
思路(1)
這題因為不能使用除法,所以可以它拆成兩個步驟,也就是前綴積以及後綴積。因為每遍歷到一個元素,就必須把該元素前面的元素相乘,再乘上該元素後面的所有元素。
也就是說,可以先把每個元素前面的所有元素相乘,得到一個前綴積的陣列。接著,再把每個元素後面的所有元素相乘,得到一個後綴積的陣列。
以
[1, 2, 3, 4]
為例,1
的前綴積會是 1 ,因為 1 前面沒有任何元素,所以直接用 1 表示。1 乘以任何數字不會有任何影響。2
的前綴積也是 1,因為 2 前面只有一個元素 1。3
的前綴積是 1 * 2,因為 3 前面有兩個元素 1 跟 2。4
的前綴積是 1 * 2 * 3,因為 4 前面有三個元素 1 跟 2 跟 3。
所以,陣列[1, 2, 3, 4]
的前綴積陣列會是[1, 1, 2, 6]
以此類推,後綴積的計算如下:
1
的後綴積會是 2 * 3 * 4 ,因為 1 後面有三個元素, 2 跟 3 跟 4。2
的後綴積是 3 * 4,因為 2 後面兩個元素 3 跟 4。3
的後綴積是 4,因為 3 後面只有一個元素 4。4
的後綴積是 1,因為 4 後面沒有任何元素,所以直接用 1 表示。1 乘以任何數字不會有任何影響。
所以,陣列[1, 2, 3, 4]
的後綴積陣列會是[24, 12, 4, 1]
最後,前綴積、後綴積兩陣列相乘,就會是最後的輸出,也就是
[24, 12, 8, 6]
。程式的寫法,會先初始化兩個陣列,分別是前綴積陣列 ( prefix )
[1, 1, 1, 1]
、後綴積陣列 ( postfix )[1, 1, 1, 1]
。前綴積陣列比較好想,會從第一個元素開始,因為第零個元素是 1。前綴積第二個元素會是,prefix[1] * nums [1]
,因為前綴積就是把前面的元素都乘過一遍了,所以只要把「第一個元素的的前綴積」 ( 也就是prefix[-1]
) 乘上「第一個元素」 (也就是 nums [i-1]
),就會是第二個元素的前綴積。後綴積也是一樣的概念。只不過要從陣列的「倒數第二個元素」開始 往前遍歷,後綴積陣列要從後面填回來的意思,因為最後一個元素的後綴積是 1。計算後綴積要善用 python 的
range(start, stop, step)
,所以 range 是range(n-2, -1, -1)
,其中 stop 不能寫 0 因為會不包含第一個元素,所以通常用 -1 表示要遍歷到起始點。
程式碼 (1)
1 | class Solution: |
思路(2)
這個方法是要做 follow up 的思路,因為可以用
O(1)
的空間複雜度解題,前提是 output 陣列不列入額外空間的計算。output 陣列初始化為
[1, 1, 1, 1]
,此陣列不列入額外空間計算,主要是透過 prefix 跟 postfix 的累乘,去乘上 result 得到結果。prefix 跟 postfix 的初始值是 1。先算 prefix 或先算 postfix 都可以,因為他們的初始值都是 1 ,所以在乘上 result 時並不會有影響,可以用前綴積
[1, 1, 2, 6]
,跟後綴積[24, 12, 4, 1]
相乘去思考。不管先算 presfix 還是 postfix,1 * 24 或 6 * 1 並不影響最後 result 結果。
程式碼 (2)
1 | class Solution: |