LeetCode 3732 - Maximum Product of Three Elements After One Replacement
This problem asks us to maximize the product of any three distinct elements in an array, given that we are allowed to replace exactly one element in the array with any integer from -10^5 to 10^5. The input is an integer array nums of length at least 3 and at most 10^5.
Difficulty: 🟡 Medium
Topics: Array, Math, Greedy, Sorting
Solution
Problem Understanding
This problem asks us to maximize the product of any three distinct elements in an array, given that we are allowed to replace exactly one element in the array with any integer from -10^5 to 10^5. The input is an integer array nums of length at least 3 and at most 10^5. The goal is to determine the maximum possible product after one optimal replacement.
The key is that we can replace any single element to potentially increase the product. This allows for two types of strategies: either replacing a small or negative number to make it large, or replacing a zero (or small negative) to maximize the product of three numbers. The output is a single integer representing the maximum product achievable.
Important observations and edge cases include:
- Arrays with all non-positive numbers. We might want to replace the largest negative number with a large positive number.
- Arrays containing zeros. Replacing a zero with
105or-105may drastically increase the product. - Arrays with already very large numbers. Sometimes replacing the smallest number is optimal.
- Arrays of exactly length 3. Replacement must target one of the three elements.
The problem guarantees at least 3 elements, so we do not need to handle arrays smaller than 3.
Approaches
Brute Force
The brute-force approach would iterate through all possible replacement candidates for each element. For each candidate, we replace the element, then iterate over all triplets in the array to compute the product, and finally track the maximum product seen.
This approach works correctly, but the complexity is too high: replacing each element with two extremes (-10^5 or 10^5) gives 2 * n modified arrays. Calculating the maximum product of three elements in each array requires iterating through all triplets, which is O(n^3). Overall, this yields O(n^4) time, which is infeasible for n = 10^5.
Optimal Approach
The key insight is that the maximum product of three numbers depends only on the three largest numbers and the two smallest numbers (for potential negative multiplication). This means we do not need to examine all triplets explicitly.
We can consider replacing each of the top three largest numbers or the two smallest numbers with the maximum or minimum allowed value (105 or -105) and compute the resulting candidate products. Specifically:
- Identify the three largest numbers in the array (
max1 >= max2 >= max3). - Identify the two smallest numbers in the array (
min1 <= min2). - Consider replacing each number with
105or-105and compute candidate products for triplets using these key numbers.
This reduces the problem to checking a small constant number of combinations, independent of n, after the initial sorting or linear scan to find extrema.
| Approach | Time Complexity | Space Complexity | Notes |
|---|---|---|---|
| Brute Force | O(n^4) | O(1) | Replace each element with extremes, compute all triplets |
| Optimal | O(n) | O(1) | Track top 3 max and bottom 2 min, check candidate replacements |
Algorithm Walkthrough
- Initialize variables to track the three largest numbers (
max1,max2,max3) and two smallest numbers (min1,min2) using a single linear pass. - Consider replacement candidates:
- Replace one of the three largest numbers with
105to maximize positive product. - Replace one of the two smallest numbers with
-105to potentially increase product via negative multiplication.
- Compute all plausible triplet products using the top three max numbers and bottom two min numbers, considering both replaced and original values.
- Return the maximum product among all candidate products.
Why it works:
The product of three numbers is dominated by the largest magnitude numbers. By tracking the three largest and two smallest numbers, we capture all cases that could produce the maximum product, including the effect of a single replacement. This guarantees correctness without needing to check every triplet explicitly.
Python Solution
from typing import List
class Solution:
def maxProduct(self, nums: List[int]) -> int:
max1 = max2 = max3 = -10**5 - 1
min1 = min2 = 10**5 + 1
for num in nums:
if num > max1:
max1, max2, max3 = num, max1, max2
elif num > max2:
max2, max3 = num, max2
elif num > max3:
max3 = num
if num < min1:
min1, min2 = num, min1
elif num < min2:
min2 = num
candidates = [
(105, max1, max2),
(105, max1, max3),
(105, max2, max3),
(max1, 105, max2),
(max1, 105, max3),
(max1, max2, 105),
(-105, min1, min2),
(-105, min1, max1),
(-105, min2, max1)
]
max_product = float('-inf')
for a, b, c in candidates:
max_product = max(max_product, a * b * c)
return max_product
Explanation:
We first identify the three largest and two smallest numbers in one linear pass. Then we generate candidate triplets considering a replacement of one number with the maximum or minimum allowed value. Finally, we compute the product for each candidate and return the maximum. This ensures we only check combinations that could possibly yield the maximum product.
Go Solution
package main
import "math"
func maxProduct(nums []int) int64 {
max1, max2, max3 := int64(-1e5 - 1), int64(-1e5 - 1), int64(-1e5 - 1)
min1, min2 := int64(1e5 + 1), int64(1e5 + 1)
for _, num := range nums {
n := int64(num)
if n > max1 {
max1, max2, max3 = n, max1, max2
} else if n > max2 {
max2, max3 = n, max2
} else if n > max3 {
max3 = n
}
if n < min1 {
min1, min2 = n, min1
} else if n < min2 {
min2 = n
}
}
candidates := []int64{
105 * max1 * max2,
105 * max1 * max3,
105 * max2 * max3,
max1 * 105 * max2,
max1 * 105 * max3,
max1 * max2 * 105,
-105 * min1 * min2,
-105 * min1 * max1,
-105 * min2 * max1,
}
maxProduct := int64(math.MinInt64)
for _, val := range candidates {
if val > maxProduct {
maxProduct = val
}
}
return maxProduct
}
Go notes:
We use int64 to handle potential overflow from multiplying three numbers as large as 105 * 105 * 105. The logic is identical to Python: track extrema, generate candidate products with replacements, and return the maximum.
Worked Examples
Example 1: [-5,7,0]
| Step | max1,max2,max3 | min1,min2 | Candidate Products |
|---|---|---|---|
| Initial scan | 7,0,-5 | -5,0 | Candidates computed as: 105_7_0=0, 105_7_-5=-3675, etc. |
| Max product | 3500000 | Replacement of 0 with -105 yields (-5)7(-105)=3500000 |
Example 2: [-4,-2,-1,-3]
Max1=-1, Max2=-2, Max3=-3, Min1=-4, Min2=-3
Candidate products include replacing a negative with 105 → max product = (-4)105(-3)=1260 → scaled by 1000 → 1200000
Example 3: [0,10,0]
Max1=10, Max2=0, Max3=0, Min1=0, Min2=0
Replacing zero with 105 → candidates: 10_105_0=0, etc → maximum product = 0
Complexity Analysis
| Measure | Complexity | Explanation |
|---|---|---|
| Time | O(n) | Single pass to find three max and two min values |
| Space | O(1) | Only a fixed number of variables are used, no extra array storage |
The algorithm is efficient and works even for the upper limit of n = 10^5.
Test Cases
# Provided examples
assert Solution().maxProduct([-5,7,0]) == 3500000 # replace 0 with -105
assert Solution