1. 解题思路
这一题思路上我一开始想的是直接法,但是没想到什么好的方法,因此就只能退而求其次,使用二分法来确定临界值,这个思路也算是比较直接的了。
于是,问题就变成了给定一个值,如何判断其前方一共有多少个可能组成的货币面值,这个问题事实上上也不那么直接,不过我们可以用容斥原理进行解答。
而要使用容斥原理的话,我们需要求出所有包含某一个元素的组合的最小公倍数,这个我们可以通过一个迭代算法来实现,由于25之内只有9个质数,因此总的计算量至多也就 2 9 2^9 29,并非不可接受。
最后,考虑到元素较多的情况下容斥原理的计算量其实还是挺大的,因此我们可以实现对货币面值进行一下简化,将那些是其他面值的整倍数的面值直接移除掉即可。
综上,我们即可最终给出我们的解答。
2. 代码实现
给出python代码实现如下:
class Solution:
def findKthSmallest(self, coins: List[int], k: int) -> int:
if 1 in coins:
return k
def filter_coins(coins):
coins = sorted(coins)
fcoins = []
for c in coins:
if any(c % x == 0 for x in fcoins):
continue
fcoins.append(c)
return coins
coins = filter_coins(coins)
n = len(coins)
lcms = defaultdict(list)
def dfs(idx, used, _lcm):
nonlocal lcms
if idx >= n:
return
dfs(idx+1, used, _lcm)
_lcm = lcm(_lcm, coins[idx])
lcms[used+1].append(_lcm)
dfs(idx+1, used+1, _lcm)
return
dfs(0, 0, 1)
def count(x):
ans = 0
flag = 1
for i in range(1, n+1):
for v in lcms[i]:
ans += flag * (x // v)
flag = -flag
return ans
l, r = 0, coins[-1] * k + 1
while r-l > 1:
m = (l+r) // 2
if count(m) >= k:
r = m
else:
l = m
return r
提交代码评测得到:耗时77ms,占用内存17.2MB。