【问题标题】:What is the time complexity of this coin changing combination algorithm?这个换币组合算法的时间复杂度是多少?
【发布时间】:2019-05-29 18:17:06
【问题描述】:

您好,我刚刚解决了这个 leetcode 问题:https://leetcode.com/problems/coin-change-2/

我们的目标是找出coins 的不同可能组合的数量,我们可以使用这些组合来生成amount,假设我们有来自每个面额的无限数量的硬币。

我知道这个问题有一个在 O(amount*len(coins)) 中运行的 DP 解决方案,我可以在下面的解决方案中添加 memoization 来实现这一点。

但是,我正在努力寻找以下天真的方法的时间复杂度:

def change(amount, coins):
    def helper(amount, coins, id):
        if amount == 0:
            return 1
        res = 0
        for i in range(id, len(coins)):
            if coins[i] <= amount:
                res += helper(amount - coins[i], coins, i)
        return res

    res = helper(amount, coins, 0)
    return res

所以我实际上在做的是一个 DFS,我尝试在回溯并移动到下一个硬币之前尽可能多地使用第一个硬币。因此,一旦我开始使用下一个硬币,我就不能再使用第一个硬币了 --> 这使我可以不计算结果中的排列。

我知道这个解决方案的时间复杂度是O(exponential),我也知道它是O(V + E),因为它是DFS。

有人可以给出时间复杂度的确切形式吗?指数项究竟是什么?或者如何计算图中的边和顶点?

【问题讨论】:

    标签: python-3.x algorithm recursion coin-change


    【解决方案1】:

    假设金额 n 非常大,并且每个硬币的值与 n 相比非常小,并且让硬币数组的大小为 c。事实上,在最坏的情况下,我们可以假设每个硬币的价值约为 1。在表示您的解决方案构建的调用堆栈的树中,每个节点将分支 c 次。树的每一级从 n 中减去硬币的值(在最坏的情况下约为 1),因此树的深度(或高度)将为 n。因此,我们正在查看高度为 n 的 c 分支树。顶点数,V = c^0 + c^1 + c^2 + c^3 + ... + c^(n-1) + c^n。你可以看到这个系列减少到here。边数 E 的计算类似。该算法的时间复杂度为 O(c^n)。

    【讨论】:

      【解决方案2】:

      这里有几点需要注意

      1. 动态编程是一个概念或想法。它本身并不是一种算法。这是一种用于提高某些算法的运行时间的技术,其中子问题可能重叠并使用预先计算的结果。有可能没有任何子问题重叠,这是人们谈论的最坏情况的复杂性。
      2. 让我们继续假设没有子问题重叠,我们采用自上而下的方法,您有 c1, c2, ... c n 作为您的硬币面额

      认为以下方法可行,

      因此,自上而下的方法看起来像这样

      一些路径将终止为以 0 结尾的叶子。(该方法产生了初始量 k 的完美分割)。有些没有。

      为了复杂起见,我们假设他们都这样做了。

      因此,在任何给定级别,您都有 nlevel_num 个节点。而且你必须遍历树的每个节点。

      最长的路径将是您从初始金额k中删除最小面额的地方。 i.i k/c1

      因此,在您的情况下,真正的时间复杂度将是 O(1+n1+n2+....nk/ c1)

      大多数此类问题都将 1 作为硬币的有效面额(或其他一些小数)以简化此表达式并使 GP 更易于计算

      【讨论】:

        猜你喜欢
        • 2020-03-14
        • 2015-06-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多