Before attempting this problem, you should be comfortable with:
Sorting - One approach sorts the array to easily access the two largest and two smallest elements
Single-Pass Min/Max Tracking - The optimal solution tracks the top 2 maximum and minimum values in one pass
Basic Array Manipulation - Understanding how to iterate and compare elements efficiently
1. Brute Force
Intuition
The product difference is (nums[a] * nums[b]) - (nums[c] * nums[d]) where all four indices are distinct. To maximize this, we want the first product as large as possible and the second product as small as possible. The brute force approach tries all valid combinations of four distinct indices.
Algorithm
Use four nested loops to select indices a, b, c, d.
Skip any iteration where indices overlap.
For each valid combination, compute the product difference.
classSolution:defmaxProductDifference(self, nums: List[int])->int:
n, res =len(nums),0for a inrange(n):for b inrange(n):if a == b:continuefor c inrange(n):if a == c or b == c:continuefor d inrange(n):if a == d or b == d or c == d:continue
res =max(res, nums[a]* nums[b]- nums[c]* nums[d])return res
publicclassSolution{publicintmaxProductDifference(int[] nums){int n = nums.length, res =0;for(int a =0; a < n; a++){for(int b =0; b < n; b++){if(a == b)continue;for(int c =0; c < n; c++){if(a == c || b == c)continue;for(int d =0; d < n; d++){if(a == d || b == d || c == d)continue;
res =Math.max(res, nums[a]* nums[b]- nums[c]* nums[d]);}}}}return res;}}
classSolution{public:intmaxProductDifference(vector<int>& nums){int n = nums.size(), res =0;for(int a =0; a < n; a++){for(int b =0; b < n; b++){if(a == b)continue;for(int c =0; c < n; c++){if(a == c || b == c)continue;for(int d =0; d < n; d++){if(a == d || b == d || c == d)continue;
res =max(res, nums[a]* nums[b]- nums[c]* nums[d]);}}}}return res;}};
classSolution{/**
* @param {number[]} nums
* @return {number}
*/maxProductDifference(nums){const n = nums.length;let res =0;for(let a =0; a < n; a++){for(let b =0; b < n; b++){if(a === b)continue;for(let c =0; c < n; c++){if(a === c || b === c)continue;for(let d =0; d < n; d++){if(a === d || b === d || c === d)continue;
res = Math.max(
res,
nums[a]* nums[b]- nums[c]* nums[d],);}}}}return res;}}
publicclassSolution{publicintMaxProductDifference(int[] nums){int n = nums.Length, res =0;for(int a =0; a < n; a++){for(int b =0; b < n; b++){if(a == b)continue;for(int c =0; c < n; c++){if(a == c || b == c)continue;for(int d =0; d < n; d++){if(a == d || b == d || c == d)continue;
res = Math.Max(res, nums[a]* nums[b]- nums[c]* nums[d]);}}}}return res;}}
funcmaxProductDifference(nums []int)int{
n :=len(nums)
res :=0for a :=0; a < n; a++{for b :=0; b < n; b++{if a == b {continue}for c :=0; c < n; c++{if a == c || b == c {continue}for d :=0; d < n; d++{if a == d || b == d || c == d {continue}if nums[a]*nums[b]-nums[c]*nums[d]> res {
res = nums[a]*nums[b]- nums[c]*nums[d]}}}}}return res
}
class Solution {funmaxProductDifference(nums: IntArray): Int {val n = nums.size
var res =0for(a in0 until n){for(b in0 until n){if(a == b)continuefor(c in0 until n){if(a == c || b == c)continuefor(d in0 until n){if(a == d || b == d || c == d)continue
res =maxOf(res, nums[a]* nums[b]- nums[c]* nums[d])}}}}return res
}}
classSolution{funcmaxProductDifference(_ nums:[Int])->Int{let n = nums.count
var res =0for a in0..<n {for b in0..<n {if a == b {continue}for c in0..<n {if a == c || b == c {continue}for d in0..<n {if a == d || b == d || c == d {continue}
res =max(res, nums[a]* nums[b]- nums[c]* nums[d])}}}}return res
}}
Time & Space Complexity
Time complexity: O(n4)
Space complexity: O(1)
2. Sorting
Intuition
To maximize the product difference, we need the two largest numbers for the first product and the two smallest numbers for the second product. After sorting, these are simply the last two and first two elements.
Algorithm
Sort the array in ascending order.
The maximum product is nums[n-1] * nums[n-2] (two largest).
The minimum product is nums[0] * nums[1] (two smallest).
Space complexity: O(1) or O(n) depending on the sorting algorithm.
3. Two Maximums and Two Minimums
Intuition
We only need the two largest and two smallest values, so we can find them in a single pass without sorting the entire array. By tracking these four values as we iterate, we achieve linear time complexity.
Algorithm
Initialize max1, max2 to 0 (or the smallest possible values) and min1, min2 to infinity (or the largest possible values).
For each number in the array:
Update max1 and max2 if the current number is among the two largest seen so far.
Update min1 and min2 if the current number is among the two smallest seen so far.
funcmaxProductDifference(nums []int)int{
max1, max2 :=0,0
min1, min2 := math.MaxInt32, math.MaxInt32
for_, num :=range nums {if num > max1 {
max2 = max1
max1 = num
}elseif num > max2 {
max2 = num
}if num < min1 {
min2 = min1
min1 = num
}elseif num < min2 {
min2 = num
}}return(max1 * max2)-(min1 * min2)}
class Solution {funmaxProductDifference(nums: IntArray): Int {var max1 =0var max2 =0var min1 = Int.MAX_VALUE
var min2 = Int.MAX_VALUE
for(num in nums){if(num > max1){
max2 = max1
max1 = num
}elseif(num > max2){
max2 = num
}if(num < min1){
min2 = min1
min1 = num
}elseif(num < min2){
min2 = num
}}return(max1 * max2)-(min1 * min2)}}
classSolution{funcmaxProductDifference(_ nums:[Int])->Int{var max1 =0, max2 =0var min1 =Int.max, min2 =Int.max
for num in nums {if num > max1 {
max2 = max1
max1 = num
}elseif num > max2 {
max2 = num
}if num < min1 {
min2 = min1
min1 = num
}elseif num < min2 {
min2 = num
}}return(max1 * max2)-(min1 * min2)}}
Time & Space Complexity
Time complexity: O(n)
Space complexity: O(1)
Common Pitfalls
Forgetting to Track Both Maximums and Minimums Separately
When updating the two largest values, failing to properly shift max1 to max2 before assigning the new max1 causes the second maximum to be lost. Similarly for minimums. Always save the old value before overwriting.
Using Incorrect Initial Values
Initializing min1 and min2 to 0 instead of infinity (or the maximum possible value) leads to incorrect results when all array elements are positive. Since the problem guarantees positive integers, initialize minimums to a large value like INT_MAX or float('inf').