JavaScript Three Sum: Find the Highest Product of Three Numbers
Question: Given an array of integers, find the highest product you can get from three of the integers. Write a function threeSum
that solves this.
const arr = [-1, 0, 2, 5, 3, -4];
threeSum(arr); // 30
Brute Force
We could use three loops to iterate through arr
and create a maxProduct
of each integer times each other integer and each other, other integer.
// O(n^3) time
const threeSum = (arr) => {
let maxProduct = 0;
for (let i=0; i<arr.length - 2; i++) {
for (let j=i+1; j<arr.length - 1; j++) {
for (let k=j+1; k<arr.length; k++) {
let product = arr[i] * arr[j] * arr[k];
if (product > maxProduct) {
maxProduct = product;
}
}
}
}
return maxProduct;
}
Sorting
If we sort the array–which we can do in O(n log n) time–then we can simply multiply the three largest integers at the end.
// O(n log n)
const threeSum = (arr) => {
sortedArr = arr.sort((a, b) => a - b);
let len = arr.length;
let maxProduct = sortedArr[len-1] * sortedArr[len-2] * sortedArr[len-3];
return maxProduct;
}
Greedy Approach
If we use a greedy approach we can obtain O(n)
time. We need to track both the highestProductOf2
and lowestProductOf2
since there can be negative numbers in our array. We’ll also track the highestProductOf3
and the absolute highest
and lowest
.
const threeSum = (arr) => {
let highest = Math.max(arr[0], arr[1]);
let lowest = Math.min(arr[0], arr[1]);
let highestProductOf2 = arr[0] * arr[1];
let lowestProductOf2 = arr[0] * arr[1];
let highestProductOf3 = arr[0] * arr[1] * arr[2];
for (let i=2; i<arr.length; i++) {
let current = arr[i];
highestProductOf3 = Math.max(
highestProductOf3,
current * highestProductOf2,
current * lowestProductOf2
);
highestProductOf2 = Math.max(
highestProductOf2,
current * highest,
current * lowest
);
lowestProductOf2 = Math.min(
lowestProductOf2,
current * highest,
current * lowest
);
highest = Math.max(highest, current);
lowest = Math.min(lowest, current);
}
return highestProductOf3;
}
Conclusion
This problem follows the classic brute force -> sorting -> greedy progression that you should look for in most interview questions. Try to solve it first using the simplest possible approach. Consider whether sorting or searching would improve the time complexity. And finally think about using a hash map and/or greedy approach.
Also note that the current solutions to not properly handle negative numbers. Always good to ask on the range for the initial array and handle appropriately as needed!
Want to improve your JavaScript? I have a list of recommended JavaScript books.