See the original problem on HackerRank.
Solutions
The brute force approach is easy: just run two nested loops and for each value \( x \) find if it exists a value equals to \( target - x \). This solution is quadratic.
Efficient solutions are based either on sorting or additional storage (e.g. frequency table, hash maps).
A sort-based solution
Suppose we sort the prices \( p \) in ascending order. Consider the sum \( p[0] + p[n-1] \) where \( n \) is the number of available prices. If this sum was less than \( m \), then we should increment the left hand index (we need to “pay more”). On the other hand, if the sum was greater than \( m \), then we should decrement the right hand index (we need to “pay less”). This leads to the following solution based on 2-pointer technique:
|
|
Clearly, some additional storage is needed to sort the array without losing the original indexes.
The overall complexity is \( O(N \cdot logN \) but it can be even optimized by using a linear-time sorting algorithm since the domain is small (e.g. counting sort or radix sort).
Lookup-efficient data structures solutions
Another approach consists in using a multimap (since duplicates are possible) to lookup every value efficiently:
|
|
A variation of this approach consists in using a frequency table. In this case, we do not keep track of the indexes with a sort of trick: when we find the matching price (\( m - p[i] \)), we just scan the array to find its position. Since this operation is perfomed only once, the solution stays linear:
|
|
Note that the weird condition freq[x] > (x == p[i])
is just syntactic sugar to say “if x
is p[i]
then we need to have at least two of such values available. For example, suppose we have:
|
|
and suppose we need to find the indexes for k=4
. When we check for the first 2
, we have:
|
|