Link: https://leetcode.com/problems/most-expensive-item-that-can-not-be-bought/
Solution:
Intuition
Not a huge fan of these mathy problems, but this one is pretty neat. We start with one key observation: all numbers after primeOne * primeTwo
can be formed. Why is this the case? It’s some number theory proof that I have no interest in getting into.
So now that we know the upper bound is primeOne * primeTwo
, we can use DP on this problem to find the largest number that cannot be formed.
Implementation (DP)
def most_expensive(primeOne, primeTwo):
@cache
def dfs(amount):
if amount == 0:
return True
if amount < 0:
return False
return dfs(amount-primeOne) or dfs(amount-primeTwo)
curr = primeOne * primeTwo
while dfs(curr):
curr -= 1
return curr
#time: o((primeOne*primeTwo)**2)
#memory: o(primeOne*primeTwo)
There is also an o(1)
math solution. I suspected this to be the case when I was solving, but I’m not very well versed in number theory. There exists a theorem called the chicken mcnugget theorem. The theorem states that the largest number that can not be formed with two distinct primes can be directly computed: mn - m - n
. Yes, its that simple.
Implementation (math)
def most_expensive(primeOne, primeTwo):
return (primeOne * primeTwo) - primeOne - primeTwo
#time: o(1)
#memory: o(1)
Review 1
What a funky problem! I remembered that we had to use the chicken mcnugget theorem, but I couldn’t remember it. I guess that’s not a bad thing. The DP solution is also kind of interesting…but you still need to know that primeOne*primeTwo
is the upper bound. All numbers past this can be formed so in the context of this problem, all gifts that cost more than primeOne*primeTwo
can be bought…so we can use DP to find a sequence of primeOne
and primeTwo
that cannot form the highest number starting from primeOne*primeTwo-1
, and decrementing. The sum is all that matters, so caching here greatly improves the complexity.