'Largest Triple Products without using sort?
I implemented the Largest Triple Products algorithm, but I use sort which makes my time complexity O(nlogn). Is there a way to implement it without a temporary sorted array?
The problem: You're given a list of n integers arr[0..(n-1)]. You must compute a list output[0..(n-1)] such that, for each index i (between 0 and n-1, inclusive), output[i] is equal to the product of the three largest elements out of arr[0..i] (or equal to -1 if i < 2, as arr[0..i] then includes fewer than three elements). Note that the three largest elements used to form any product may have the same values as one another, but they must be at different indices in arr.
Example:
var arr_2 = [2, 4, 7, 1, 5, 3];
var expected_2 = [-1, -1, 56, 56, 140, 140];
My solution:
function findMaxProduct(arr) {
// Write your code here
if(!arr || arr.length === 0) return [];
let helper = arr.slice();
helper.sort((a,b)=>a-b); // THIS IS THE SORT
let ans = [];
let prod = 1;
for(let i=0; i<arr.length; i++) {
if(i < 2) {
prod *= arr[i];
ans.push(-1);
}
else {
if(i === 3) {
prod *= arr[i];
ans.push(prod);
} else if(arr[i] < helper[0]) {
ans.push(prod);
} else {
const min = helper.shift();
prod /= min;
prod *= arr[i];
ans.push(prod);
}
}
}
return ans;
}
Thanks
Solution 1:[1]
You don't need to sort it. You just maintain an array of the largest three elements at each index.
For the first three elements it is simple you just assign the product of them to the third element in the result.
For the next elements, you add the current element to the three-largest-element-array and sort it and take the elements from 1 to 3 ( the largest three ) and assign the product of those at that index in result array. Then update the three-element-array with largest three.
- Complexity :
This sort and slice of three-element-array should be O(1) because each time atmost 4 elements are there in the array.
Overall complexity is O(n).
You can do it as follows :
function findMaxProduct(arr) {
if(!arr) return [];
if (arr.length < 3) return arr.slice().fill(-1)
let t = arr.slice(0,3)
let ans = arr.slice().fill(-1,0,2) //fill first two with -1
ans[2] = t[0]*t[1]*t[2];
for(let i=3; i<arr.length; i++) {
t.push(arr[i]);
t = t.sort().slice(1,4);
ans[i] = t[0]*t[1]*t[2];
}
return ans;
}
Solution 2:[2]
You can make an array that holds three currently largest integers, and update that array as you passing through original array. That's how you will always have three currently largest numbers and you will be able to solve this with O(n) time complexity.
Solution 3:[3]
I think there's a faster and more efficient way to go about this. This is a similar thought process as @Q2Learn, using Python; just faster:
def findMaxProduct(arr):
#create a copy of arr
solution = arr.copy()
# make first 2 elements -1
for i in range(0,2):
solution[i] = -1
#for each item in copy starting from index 2, multiply item from 2 indices b'4 (notice how each index of arr being multiplied is reduced by 2, 1 and then 0, to accommodate each move)
for i in range(2, len(arr)):
solution[i] = arr[i-2] * arr[i-1] * arr[i]
return solution
check = findMaxProduct(arr)
print(check)
Solution 4:[4]
public int[] LargestTripleProducts(int[] input)
{
var ansArr = new int[input.Length];
var firstLargetst = input[0];
var secondLargetst = input[1];
ansArr[0] = ansArr[1] = -1;
for (int i = 2; i < input.Length; i++)
{
ansArr[i] = firstLargetst * secondLargetst * input[i];
if (firstLargetst < input[i] && firstLargetst < secondLargetst)
{
firstLargetst= input[i];
continue;
}
if (secondLargetst < input[i] && secondLargetst < firstLargetst)
{
secondLargetst= input[i];
}
}
return ansArr;
}
Solution 5:[5]
Python solution based on @SomeDude answer above. See explanation there.
def findMaxProduct(arr):
if not arr:
return None
if len(arr) < 3:
for i in range(len(arr)):
arr[i] = -1
return arr
three_largest_elem = arr[0:3]
answer = arr.copy()
for i in range(0, 2):
answer[i] = -1
answer[2] = three_largest_elem[0] * three_largest_elem[1] * three_largest_elem[2]
for i in range(3, len(arr)):
three_largest_elem.append(arr[i])
three_largest_elem = sorted(three_largest_elem)
three_largest_elem = three_largest_elem[1:4]
answer[i] = three_largest_elem[0] * three_largest_elem[1] * three_largest_elem[2]
return answer #Time: O(1) n <= 4, to Overall O(n) | Space: O(1)
Solution 6:[6]
I am keeping the array ordered (manually). Then just get the first 3 elements.
function findMaxProduct(arr) {
let results = [];
let heap = [];
for (let i = 0; i < arr.length; i++) {
// Insert the new element in the correct position
for (let j = 0; j < heap.length; j++) {
if (arr[i] >= heap[j]) {
heap.splice(j, 0, arr[i]);
break;
}
}
// No position found, insert at the end
if (heap.length != i + 1) {
heap.push(arr[i]);
}
if (i < 2) {
results.push(-1);
} else {
results.push(heap[0] * heap[1] * heap[2]);
}
}
return results;
}
Solution 7:[7]
Python has it's in-built package heapq, look at it for it.
Credit: Martin
> Helper function for any type of calculations
import math
> Heap algorithm
import heapq
> Create empty list to append output values
output = []
def findMaxProduct(arr):
out = []
h = []
for e in arr:
heapq.heappush(h, e)
if len(h) < 3:
out.append(-1)
else:
if len(h) > 3:
heapq.heappop(h)
out.append(h[0] * h[1] * h[2])
return out
Hope this helps!
Solution 8:[8]
Single Scan Algorithm O(n)
We don't need to necessarily sort the given array to find the maximum product. Instead, we can only find the three largest values (x, y, z) in the given stage of iteration:
JavaScript:
function findMaxProduct(arr) {
let reults = []
let x = 0
let y = 0
let z = 0
for(let i=0; i<arr.length; i++) {
n = arr[i]
if (n > x) {
z = y
y = x
x = n
}
if (n < x && n > y) {
z = y
y = n
}
if (n < y && n > z) {
z = n
}
ans = x*y*z
if (ans === 0) {
results.push(-1)
} else {
results.push(ans)
}
return ans;
}
Python:
def findMaxProduct(arr):
results = []
if not arr:
return []
x = 0
y = 0
z = 0
for i, n in enumerate(arr):
if n > x:
z = y
y = x
x = n
if n < x and n > y:
z = y
y = n
if n < y and n > z:
z = n
ans = x*y*z
if ans == 0:
results.append(-1)
else:
results.append(ans)
print(results)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Bane2000 |
Solution 3 | Daniel Darku |
Solution 4 | Osama Aziz |
Solution 5 | Q2Learn |
Solution 6 | Jonathas Costa |
Solution 7 | Ishwor Bhusal |
Solution 8 | Roozbeh |