最近在刷leetcode。现在涉及到的是70 climbing staircase。我第一步想到的解法是递归,按照这个思路,其实很快就有答案。
int climbStairs(int n) {
if(n > 0 && rec[n] != 0)
{
return rec[n];
}
if(n == 0)
{
return 1;
}
else if(n < 0)
{
return 0;
}
int count = 0;
for(int i = 0; i < 2; i++)
{
count += climbStairs(n - steps[i]);
}
rec[n] = count;
return count;
}
这里使用了int rec[46]来缓存结果加快速度。效果很好,速度也比较满意。
但是毕竟这个题是有关动态规划的,详细看了下动态规划的思路。大概就是拆解第十步。
F(10) = F(9) + F(8),想一想也很好理解。F(9)到F(10)只有1步的走法,没有其它的选择。F(8)到F(10)也只有2步的走法,没有其它的选择。所以步数和以前是相同的。
改了一下代码如下:
int climbStairs(int n) {
if(n > 0 && rec[n] != 0)
{
return rec[n];
}
if (n < 1){
return 0;
}
if (n == 1){
return 1;
}
if (n == 2){
return 2;
}
int count = climbStairs(n - 1) + climbStairs(n - 2);
rec[n] = count;
return count;
}
从代码来说,本质上和之前其实也差不多。一个是从头开始,一个是倒着开始。leetcode的耗时也差不多。
回顾一下前阵看的北京交大的算法课,动态规划的流程如下:
1 分析最优子结构。
2 设计状态转移方程。
3 找到计算最优值的算法。
我也是刚学动态规划,感觉动态规划能干的事情,其实很多其它算法也能写出来,那么DP的优点在哪呢?估计是一个套路吧,有这个套路解决问题就有固定流程了。但是时间空间复杂度未必能做到最优。
第二就是动态规划和树的感觉比较接近,我接触的几个都可以用递归来处理,都存在可以剪枝的优化。可能还是接触的少吧。
B站看了一个图,总结的比较容易懂: