Leetcode 3116. Kth Smallest Amount With Single Denomination Combination

文章介绍了如何使用二分法和容斥原理解决LeetCode题目3116,涉及计算给定面额组合中第k小的总金额,通过优化和简化面额,以及使用深度优先搜索和迭代算法求解,最终给出了Python代码实现,展示了高效的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值