Product of Array Except Self

題目描述

給定整數陣列 nums,回傳陣列 answer,其中 answer[i] 等於 nums 中除了 nums[i] 以外所有元素的乘積。不能使用除法,且要求 O(n) 時間。

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

輸入:nums = [-1,1,0,-3,3]
輸出:[0,0,9,0,0]

解題思路

1

前綴積

從左到右遍歷,answer[i] 存放 nums[0]×nums[1]×...×nums[i-1],answer[0]=1(左邊沒有元素)

2

後綴積

從右到左遍歷,用變數 suffix 累積 nums[i+1]×...×nums[n-1],每步將 answer[i] 乘上 suffix

3

合併

兩次遍歷後 answer[i] = 左邊所有元素乘積 × 右邊所有元素乘積,恰好跳過 nums[i]

程式碼

C#

csharp
public class Solution {
    public int[] ProductExceptSelf(int[] nums) {
        int n = nums.Length;
        int[] answer = new int[n];
 
        // 前綴積:answer[i] 先存左邊的累積乘積
        answer[0] = 1;
        for (int i = 1; i < n; i++)
            answer[i] = answer[i - 1] * nums[i - 1];
 
        // 後綴積:用一個變數從右邊累積,乘進 answer
        int suffix = 1;
        for (int i = n - 2; i >= 0; i--) {
            suffix *= nums[i + 1];
            answer[i] *= suffix;
        }
        return answer;
    }
}

TypeScript

typescript
function productExceptSelf(nums: number[]): number[] {
    const n = nums.length;
    const answer = new Array(n);
 
    // 前綴積
    answer[0] = 1;
    for (let i = 1; i < n; i++)
        answer[i] = answer[i - 1] * nums[i - 1];
 
    // 後綴積
    let suffix = 1;
    for (let i = n - 2; i >= 0; i--) {
        suffix *= nums[i + 1];
        answer[i] *= suffix;
    }
    return answer;
}

Python

python
def productExceptSelf(nums: list[int]) -> list[int]:
    n = len(nums)
    answer = [1] * n
 
    # 前綴積
    for i in range(1, n):
        answer[i] = answer[i - 1] * nums[i - 1]
 
    # 後綴積
    suffix = 1
    for i in range(n - 2, -1, -1):
        suffix *= nums[i + 1]
        answer[i] *= suffix
 
    return answer

複雜度分析

| | Time | Space | |--|------|-------| | 本解法 | O(n) | O(1) |

第一次從左到右遍歷 O(n) 建前綴積,第二次從右到左遍歷 O(n) 乘後綴積,合計 O(2n) = O(n)。輸出陣列是題目要求的回傳值不計入額外空間,只用一個 suffix 變數,空間 O(1)。

邊界情況

圖解

nums: [1,2,3,4]
左→右
前綴積: [1,1,2,6]
相乘
後綴積: [24,12,4,1]
相乘
answer: [24,12,8,6]

圖表展示 [1,2,3,4] 的兩趟掃描。前綴積 [1,1,2,6] 表示:index 0 左邊沒有元素(1),index 1 左邊是 1,index 2 左邊乘積是 1x2=2,index 3 是 1x2x3=6。後綴積同理從右算起。兩者對應位置相乘得到最終答案。

進階觀點

💡面試追問

  • 為什麼不能用除法? 題目明確禁止。即使允許,陣列含 0 時會除以零。需要分三種情況處理:零個 0(正常除法)、一個 0(只有 0 的位置有非零結果)、多個 0(全部為 0)。邏輯複雜且容易出錯。
  • 如果允許除法? 先算全部乘積 P,answer[i] = P / nums[i]。但必須特別處理上述 0 的三種情況,面試時容易遺漏邊界。
  • 這個前綴/後綴技巧還能用在哪? Trapping Rain Water(前綴最大高度 × 後綴最大高度)、Range Sum Query(前綴和查詢區間和)都使用類似的「預計算左右兩側資訊」策略。

理解測驗

🤔 為什麼 answer[i] = prefix[i] × suffix[i] 就是除自身外的乘積?

🤔 nums = [0, 1, 2] 時,answer 是什麼?

你可能也想看

151. Reverse Words in a String334. Increasing Triplet Subsequence

按 ← → 鍵切換課程