最大乘積子數組的描述是:
給定一個整數數組 nums,找到一個具有最大乘積的子數組,並返回乘積。
產生測試案例,以便答案適合32位元整數。
例如:
Input: nums = [2, 3, -2, 4] Output: 6 Explanation: [2, 3] has the largest product 6.
Input: nums = [-2, 0, -1] Output: 0 Explanation: The result cannot be 2, because [-2, -1] is not a subarray.
現在,使用暴力方法,我們可以透過巢狀循環來解決它。
由於我們最終要得到最大的乘積,所以我們先找出數組中的最大值:
let max = Math.max(...nums);
然後,當我們遍歷每個數字時,我們可以不斷地將它們與其他剩餘的數字相乘,建立一個總數。一旦這個總數超過 max,我們就可以更新 max 以指向這個新值:
for (let i = 0; i < nums.length; i++) { let total = nums[i]; for (let j = i + 1; j < nums.length; j++) { total *= nums[j]; if (total > max) { max = total; } } }
最後,我們可以回到 max。因此,我們最終解決方案的第一次嘗試如下所示:
function maxProduct(nums: number[]): number { let max = Math.max(...nums); for (let i = 0; i < nums.length; i++) { let total = nums[i]; for (let j = i + 1; j < nums.length; j++) { total *= nums[j]; if (total > max) { max = total; } } } return max; }
時間複雜度為
22 🎜>)O(n^2) O(nO(nn
空間複雜度為
O
(
1
let currentMax = nums[0]; let currentMin = nums[0]; let result = nums[0];)
O(1)
for (let i = 1; i < nums.length; i++) { currentMax = Math.max(nums[i], nums[i] * currentMax); currentMin = Math.min(nums[i], nums[i] * currentMin); result = Math.max(result, currentMax); }
O(1)
Math.max(3, 3 * -2)
因為我們不需要額外的儲存空間。
再說一次,這只是暴力嘗試。那麼,讓我們深吸一口氣,看看另一個解決方案。
Math.min(3, 3 * -2)
這個新解決方案的想法是在我們遍歷數組中的每個數字時保留兩個不同的最大值和最小值。原因是處理負值,我們很快就會看到。
currentMax // 3 currentMin // -6
Math.max(-4, -4 * 3)
Note |
---|
If we were to multiply it with currentMin, we reach this value: -4 * -6 = 24. |
Also, let's look at our currentMin options:
Math.min(-4, -4 * -6)
This has to be -4 again, but something feels off.
The catch is that when we have negative numbers consecutively, our sign alternates, which affects the maximum result we need. That's why we're keeping track of the minimum value in the first case: to keep track of the sign.
Since the issue is just alternating signs, we can simply swap the maximum and minimum values when we're looking at a negative number before updating those values:
if (nums[i] < 0) { [currentMax, currentMin] = [currentMin, currentMax]; }
Also, note that we're taking the product of each previous subarray as we go, essentially solving a smaller portion of the problem.
And that's it, our final solution looks like this:
function maxProduct(nums: number[]): number { let currentMax = nums[0]; let currentMin = nums[0]; let result = nums[0]; for (let i = 1; i < nums.length; i++) { if (nums[i] < 0) { [currentMax, currentMin] = [currentMin, currentMax]; } currentMax = Math.max(nums[i], nums[i] * currentMax); currentMin = Math.min(nums[i], nums[i] * currentMin); result = Math.max(result, currentMax); } return result; }
The time complexity for this solution is O(n) because we go through each number once doing a constant operation.
Note |
---|
Math.max() and Math.min() are constant operations here, since we're comparing two values only. However, if we were to find max or min of a whole array, it would be O(n) as the time complexity of the operation would increase proportionately to the size of the array. |
The space complexity is O(1) since we don't need any additional storage.
The next problem on the list is called Word Break. Until then, happy coding.
以上是LeetCode冥想:最大乘積子數組的詳細內容。更多資訊請關注PHP中文網其他相關文章!