Project Euler 793 - Median of Products
Official link: https://projecteuler.net/problem=793
Thought Process
A very fun problem, requires precise implementation.
Obviously we can just find all the products, sort and the take the middle element, but this will take O(n^2 + nlog(n)) time to append all the elements and the sort it, where n = 1,000,003. This will take far too long.
This problem reminded me of a much simpler problem: See if a number is a sum of 2 elements in a list. The common solution is to loop through the list and then see if (required sum - current element) is inside the list.
I did something similar, I detail my algorithm below
First lets sort the set S = {S0, ... Sn-1}
Using a binary search let low = S0*S1, high = Sn-2*Sn-1, and m be the middle value. Let this m be our initial guess for the median
There are going to be nC2 = n(n - 1)/2 pairwise products and therefore if there are n(n-1)/4 products which are less than m, then m is the median of this set by definition.
Therefore, we need loop through the set S only once for each m, which is the crucial part to lower the time complexity (Same as the easy example problem), let's say we are on element Si, then we find the maximal element, j, such that Si*Sj ≤ m, we can do this with a binary search again in S by search for the closest Sj to m/Si
Once we have found j, it means that there will be j - i products which do not exceed m because we must have that i < j by the problem definition
Once we have found the total products less than m, if the number is greater than our goal (n(n-1)/4), then we know that this guess is too high, we let high = mid, otherwise, if we have too little then let low = mid
After the binary search we will have found our median
It takes O(nlog(n)) time to sort the set S, Then the remaining part takes nlog(n)log(Sn-2*Sn-1), because we perform a binary search for each element in n and then log(Sn-2*Sn-1) is due to the guesses of m.
Therefore our new time complexity is O(nlog(n) +nlog(n)log(Sn-2*Sn-1)) = O(nlog(n)log(Sn-2*Sn-1)) which is considerably faster than before!
Interactive Code
Enter an integer (yourinput)
Code will output M(yourinput)