假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
比如:
n = 2,结果有两种:
1 + 1
2
n = 3,结果有三种:
1 + 1 + 1
1 + 2
2 + 1
其实只要算出后面的结果,就能清楚这就是一个斐波那契数列,公式为:f(n) = f(n-1) + f(n-2),用通俗的话来说就是当前结果等于上两层相加的结果
使用 PHP 来实现算法逻辑:
function climbStairs(int $n) : int {
if ($n <= 2) {
return $n;
}
[$dp1, $dp2] = [1, 2];
for ($i = 2; $i < $n; $i++) {
[$dp1, $dp2] = [$dp2, $dp1 + $dp2];
}
return $dp2;
}
使用 Go 来实现算法逻辑:
func climbStairs(n int) int {
if n <= 2 {
return n
}
dp1, dp2 := 1, 2
for i := 2; i < n; i++ {
dp1, dp2 = dp2, dp1 + dp2
}
return dp2
}
使用 TypeScript 来实现算法逻辑:
function climbStairs(n: number) : number {
if (n <= 2) {
return n;
}
let dp1 = 1;
let dp2 = 2;
for (let i = 2; i < n; i++) {
[dp1, dp2] = [dp2, dp1 + dp2];
}
return dp2;
}
后来想想这段逻辑其实可以优化成递归的方式更简便去实现:
function climbStairs(int $n) : int {
if ($n <= 2) {
return $n;
}
return climbStairs($n - 1) + climbStairs($n - 2);
}
Go 与 TypeScript 的实现方式与 PHP 大同小异,这里就不例举了
———————————————————————————————————————————
2023.6.14 后记:通过 Go 代码运行耗时比较,如果这个 n 的值很大,使用递归的方式就会非常耗时。因为每次递归的时候都需要再进行两次递归,具体次数则为 2 的 n 次方,再加上函数的作用域是在栈上,频繁入栈出栈也会损耗一定的时间,所以最佳方式还是一开始的那段实现逻辑。通过实践还是证明,优雅的解决方式不一定是性能最佳的,有时候不需要过度封装反而效果更好。