寻找最小阶梯成本的动态规划问题的错误答案
Posted
技术标签:
【中文标题】寻找最小阶梯成本的动态规划问题的错误答案【英文标题】:Wrong answer to dynamic programming problem of finding minimum stair cost 【发布时间】:2019-12-07 21:30:05 【问题描述】:我正在尝试解决 Leetcode 上的以下问题:
在楼梯上,第 i 个步骤有一些非负成本
cost[i]
分配(0 索引)。支付费用后,您可以爬上一级或两级台阶。 您需要找到到达楼层顶部的最低成本,您可以从索引为 0 的台阶开始,也可以从索引为 1 的台阶开始。
到目前为止,这是我的解决方案。我相信我没有正确考虑到我可以从 0 级或 1 级开始这一事实,而且我不知道该怎么做。
class Solution
public:
int minCostClimbingStairs(vector<int>& cost)
return helper(cost, cost.size() - 1);
int helper(vector<int>& cost, int currStair)
static vector<double> minCost(cost.size(), 0);
minCost[0] = cost[0];
minCost[1] = cost[1];
if (currStair < 0 || cost.size() <= 1)
return 0;
if (minCost[currStair] > 0)
return minCost[currStair];
return minCost[currStair] = min(helper(cost, currStair - 1), helper(cost, currStair - 2)) + cost[currStair];
;
【问题讨论】:
【参考方案1】:这是非常正确的想法,但我认为它是自上而下和自下而上方法的混合。
由于问题告诉我们可以从步骤 0 或 1 开始,我认为从前到后处理 cost
数组更直观——您仍然可以使用自上而下的递归 DP 方法。重新做。这样更容易区分从第 0 步或第 1 步开始。您的代码返回的最终解决方案始终是minCost[minCost.size()-1]
,它没有考虑到这一点。
使用static
向量使函数成为非idempotent,因此它会在第二次运行时保留陈旧的值。就 Leetcode 而言,这不会影响正确性,因为它似乎为每个测试用例创建了一个新的类实例。尽管如此,这似乎与上述一般误解有关;初始化 0 和 1 索引并没有像您想象的那样设置正确的基本情况(这就是您在自下而上的方法中设置基本情况的方式)。
考虑到这一点,从第一个楼梯开始解决问题,然后向前走到最后一个楼梯。非静态初始化缓存向量,然后从索引 0 递归填充缓存。禁止的 2n 分支因子将由缓存处理,将复杂度降低到线性,最终结果将是从楼梯 0 或 1 开始的最小成本。问题将输入 cost
向量限制为 2 <= cost.size()
的事实是一个很大的提示;我们知道minCost[0]
和minCost[1]
始终可以在没有先决条件的情况下进行选择。
另一个小问题是,使用 0 作为空缓存标志可能会在用零填充的巨大向量上超时。由于我们需要区分未设置的索引和0,我们应该使用-1作为标志来表示未设置的缓存索引。
class Solution
public:
int minCostClimbingStairs(vector<int>& cost)
vector<int> minCost(cost.size(), -1);
helper(cost, 0, minCost);
return min(minCost[0], minCost[1]);
int helper(vector<int>& cost, int currStair, vector<int>& minCost)
if (currStair >= cost.size()) return 0;
else if (minCost[currStair] >= 0)
return minCost[currStair];
return minCost[currStair] = cost[currStair] +
min(helper(cost, currStair + 1, minCost),
helper(cost, currStair + 2, minCost));
;
【讨论】:
以上是关于寻找最小阶梯成本的动态规划问题的错误答案的主要内容,如果未能解决你的问题,请参考以下文章
Leetcode算法初学——动态规划算法“使用最小花费爬楼梯”