給你一個整數陣列 nums
,返回 陣列 answer
,其中 answer[i]
等於 nums
中除 nums[i]
之外其餘各元素的乘積 。
題目資料 保證 陣列 nums
之中任意元素的全部字首元素和字尾的乘積都在 32 位 整數範圍內。
請 不要使用除法,且在 O(n)
時間複雜度內完成此題。
示例 1:
輸入: nums = [1,2,3,4]
輸出: [24,12,8,6]
示例 2:
輸入: nums = [-1,1,0,-3,3]
輸出: [0,0,9,0,0]
提示:
2 <= nums.length <= 105
-30 <= nums[i] <= 30
- 保證 陣列
nums
之中任意元素的全部字首元素和字尾的乘積都在 32 位 整數範圍內
思路
審題:
- 陣列
nums
之中任意元素的全部字首元素和字尾的乘積都在 32 位 整數範圍內。 可以用int儲存所有乘積 - 不要使用除法 考慮到可能存在0
目標:ans[i] 是第i個元素前後兩邊元素乘積
難點:如何減少運算次數,考慮ans[i]和ans[i-1],存在大量重複計算
解決:由字首和思想,可將計算結果儲存,減少重複計算
實現:
-
開兩個陣列分別計算字首字尾乘積
時間複雜度O(n) 空間複雜度O(n)
vector<int> productExceptSelf(vector<int>& nums) { int size = nums.size(); vector<int> l = vector<int>(size,1);//字首乘積 vector<int> r = vector<int>(size,1);//字尾乘積 vector<int> ans = vector<int>(size,1); //計算字首積 for(int i=1;i<size;i++) { l[i]=l[i-1]*nums[i-1]; } //計算字尾積 for(int i=size-2;i>=0;i--) { r[i]=r[i+1]*nums[i+1]; } //計算ans for(int i=0;i<size;i++) { ans[i]=l[i]*r[i]; } return ans; }
-
最佳化:利用ans陣列儲存計算中間值
vector<int> productExceptSelf(vector<int>& nums) { int size = nums.size(); vector<int> ans = vector<int>(size,1); //計算字首積 for(int i=1;i<size;i++) { ans[i]=nums[i-1]*ans[i-1]; } //ans[i]為0到i-1乘積 mul為i+1到nums[size-1]乘積 注意邊界 從倒數第二個開始 int mul = 1; for(int i = size-2;i>=0;i--) { mul*=nums[i+1]; ans[i]*=mul; } return ans; }
總結
重複計算——>字首和——>儲存計算中間值
進一步最佳化——>”原地儲存”