【问题标题】:Dyanamic Programming - Coin Change Problem动态规划 - 硬币找零问题
【发布时间】:2020-09-22 03:39:59
【问题描述】:

我正在从hackerrank解决以下问题 https://www.hackerrank.com/challenges/coin-change/problem

我无法解决问题,所以我看了社论,他们提到了

T(i, m) = T(i, m-i)+T(i+1, m)

我无法全面了解此解决方案为何能在更高级别上发挥作用。 (如 CLRS 中的证明或简单易懂的示例)

我写的解决方案如下

fun(m){
 //base cases
 count = 0;
 for(i..n){
  count+= fun(m-i);
 }
}

我的解决方案不起作用,因为有一些重复调用。但是编辑是如何工作的,我的解决方案和更高级别的编辑有什么区别..

【问题讨论】:

  • 你确定这是公式吗?我觉得应该是T(i, m) = T(i, m-i)+T(i - 1, m)...
  • i 从 0 开始所以是 i+1

标签: algorithm recursion dynamic-programming


【解决方案1】:

我认为为了让这个工作你必须清楚地定义 T 是什么。即,让我们将 T(i,m) 定义为仅使用索引至少为 i 的硬币对 m 个单位进行更改的方式数(即,我们只查看第 i 个硬币,第 (i+1) 个硬币,所有忽略第一个 i-1 个硬币的方法)。此外,我们定义了一个数组 C,使得 C[i] 是第 i 个硬币的值(请注意,通常 C[i] 与 i 不同)。结果,如果有 n 个硬币(即 C 的长度为 n)并且我们想为 W 个单位找零,我们正在寻找值 T(0, W) 作为我们的答案(确保你能明白为什么会这样在这一点上就是这样!)。

现在,我们继续构造 T(i,m) 的递归定义。请注意,我们的解决方案要么包含额外的第 i 个硬币,要么不包含。如果确实如此,我们的新目标将只是 m - C[i] 并且为此进行更改的方法的数量是 T(i,m - C[i]) (因为我们的新目标现在是 C[ i] 小于 m)。在另一种情况下,我们的解决方案不包含第 i 个硬币。在这种情况下,我们保持目标值不变,但只考虑索引大于 i 的硬币。即,在这种情况下进行改变的方式的数量是T(i+1,m)。由于这些案例是不相交且详尽的(要么将第 i 个硬币放入解决方案中,要么不放入!),我们有这个

T(i,m) = T(i, m-C[i]) + T(i+1,m)

这与您所拥有的非常相似(C[i] 差异很重要)。请注意,如果 m

现在剩下的就是计算 T(0, W),您可以轻松地递归计算。但是,您可能注意到许多子问题重复出现,这使得解决方案变得缓慢。解决方案是使用称为动态编程或记忆的东西。即,每当计算解决方案时,将其值添加到表中(例如 T[i,m],其中 T 是 n x W 大小的 2D 数组)。然后,每当您递归计算某些东西时,请先检查表格,这样您就不会两次计算相同的东西。这称为记忆。动态编程很简单,除非您使用一点远见来按照需要的顺序计算事物。例如,我将首先计算基本情况,即列 T[ 。 , 0]。然后我将根据递归定义计算与该行和列接壤的所有值。

【讨论】:

  • 是的,它非常相似,但请注意,您可以拥有无​​限数量的每个硬币。此外,您正试图达到一个目标数字,而不是在给定权重约束的情况下最大化利润。
猜你喜欢
  • 2015-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-25
  • 1970-01-01
  • 1970-01-01
  • 2020-04-19
  • 1970-01-01
相关资源
最近更新 更多