【问题标题】:Coin Change analysis硬币变化分析
【发布时间】:2013-06-21 03:39:45
【问题描述】:

{1,3,5} 面额硬币;总和 = 11。 找到可用于计算总和的最小硬币数量 (我们可以使用任意数量的每种面额的硬币)

我搜索了这个硬币变化问题的运行时间复杂度,特别是使用动态编程方法。但无法在任何地方找到解释。

如何计算非动态解决方案的复杂度,然后将其更改为动态解决方案? (不是贪婪的)

编辑:

这是一个要求分析的实现。

public int findCoinChange(int[] coins, int sum,int count) {

    int ret = 0, maxRet = -1;
    if(sum ==0)maxRet = count;
    else if(sum < 0)maxRet = -1;
    else{
        for(int i:coins){
            ret = findCoinChange(coins, sum - i,count+1);
            if(maxRet< 0)maxRet = ret;
            else if(ret >=0 && ret < maxRet){
                    maxRet = ret;
                }
            }
    }
    if(maxRet < 0)return -1;
    else return maxRet;
}

对我来说看起来像是组合爆炸。但是我不确定如何为此推断运行时间复杂度。

【问题讨论】:

  • 我认为贪婪不会解决这个问题。
  • thefourtheye - 贪婪并不总是提供最佳解决方案,例如Sum=9;{1,4,5} 贪心会给出 - {5,1,1,1,1} 最优是 {4,4}
  • @arpitgautam 正确。我正是这个意思。如果一个程序对某些输入有效而对其他输入失败,则它不会被视为正确的程序。所以贪心是行不通的。您在评论中的示例应为 {4, 5}
  • 对,打错字了。

标签: algorithm


【解决方案1】:

这个问题的dynamic programming solution很明显O(k * n)(嵌套循环,等等等等)其中k是硬币的数量,n是改变的金额正在制作中。

我不知道你所说的非动态编程解决方案是什么意思。抱歉,您将指定您的意思是什么算法。 greedy algorithm fails 在某些情况下,所以你不应该指的是那个。你的意思是线性规划解决方案吗?这是解决这个问题的一种糟糕的方法,因为我们不知道复杂性是什么,并且可以让它任意缓慢地运行。

我也不知道您所说的“将其更改为动态的”是什么意思。

【讨论】:

  • 你是对的,贪婪和线性不是要走的路。我指的是使用递归。我们试图通过从 sum 中减去一个面额然后解决子问题来将问题简化为子问题。如果我们最后得到一个零,我们就有了一条可追溯的路径,毕竟我们会寻找最小的一个。
  • 问题是关于分析硬币找零问题的递归解决方案的复杂性。这与贪婪/dp 解决方案无关。我试了一下——递归树最多是n * k。但它有很多重复的分支。我不知道如何从那里开始。
  • @Raghu:来自问题:“我特别使用动态编程方法搜索了这个硬币更改问题的运行时间复杂度。但无法在任何地方找到解释。
  • 递归解决方案的复杂性与计算斐波那契数列的递归解决方案非常相似。然而,Fib 构建了一个二叉树,其复杂性很容易被视为 O(2^n) 更改将取决于您的面额中硬币的数量和大小。设置 D={1, 5, 12, 25} 随着 N 变大,更多的面额集将发挥作用,导致更多的孩子朝向树的根部。我认为,一般而言,您可以放心地说 O(k^n)。
  • en.wikipedia.org/wiki/Change-making_problem 用于复杂度分析,这个问题是整数背包问题的一个特例,它是弱np难,可以在伪多项式时间内求解。
猜你喜欢
  • 2018-08-02
  • 1970-01-01
  • 1970-01-01
  • 2011-05-11
  • 2016-01-24
  • 2017-10-28
  • 2014-01-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多