返回

动态规划解决爬楼梯问题,掌握第四种解法,面试加分利器!

前端

动态规划之爬楼梯问题,掌握第四种解法,让你在面试中脱颖而出!

引言

动态规划是一种解决优化问题的有效算法,在解决爬楼梯问题上,它有着出色的表现。本文将从四个不同的解法出发,深入剖析动态规划解决爬楼梯问题的思路和技巧,重点介绍第四种解法,为你的面试之路添砖加瓦。

解法一:自上而下递归

自上而下递归是一种经典的动态规划解法,从上至下逐层计算出结果。对于爬楼梯问题,可以定义函数 f(n),表示爬到第 n 级楼梯需要的最小花费。显然,有以下递推关系:

f(n) = f(n-1) + 1  // 爬一级楼梯
f(n) = f(n-2) + 1  // 爬两级楼梯

自上而下递归的实现代码如下:

def climb_stairs_rec(n):
  if n == 0:
    return 0
  elif n == 1:
    return 1
  else:
    return climb_stairs_rec(n-1) + climb_stairs_rec(n-2)

解法二:缓存结果减少重复计算

自上而下递归存在重复计算的问题,为了减少重复计算,可以引入一个字典来缓存结果。当计算 f(n) 时,首先检查字典中是否有缓存的结果,如果有,直接返回;如果没有,则计算 f(n) 并将结果缓存到字典中。

def climb_stairs_rec_cache(n):
  cache = {}
  def inner(n):
    if n in cache:
      return cache[n]
    elif n == 0:
      cache[n] = 0
      return 0
    elif n == 1:
      cache[n] = 1
      return 1
    else:
      result = inner(n-1) + inner(n-2)
      cache[n] = result
      return result
  return inner(n)

解法三:自下而上的写法

自下而上是一种更直接的动态规划解法,从下至上逐层计算出结果。对于爬楼梯问题,可以定义数组 dp,其中 dp[n] 表示爬到第 n 级楼梯需要的最小花费。显然,有以下递推关系:

dp[n] = dp[n-1] + 1  // 爬一级楼梯
dp[n] = dp[n-2] + 1  // 爬两级楼梯

自下而上的实现代码如下:

def climb_stairs_dp(n):
  if n == 0:
    return 0
  dp = [0] * (n+1)
  dp[1] = 1
  for i in range(2, n+1):
    dp[i] = dp[i-1] + dp[i-2]
  return dp[n]

解法四:再次优化,其实每次计算

观察自下而上的解法可以发现,在计算 dp[i] 时,只需要用到 dp[i-1]dp[i-2]。因此,可以将空间复杂度优化到 O(1)。

def climb_stairs_dp_opt(n):
  if n == 0:
    return 0
  pre_pre, pre = 0, 1
  for i in range(2, n+1):
    cur = pre + pre_pre
    pre_pre = pre
    pre = cur
  return pre

总结

动态规划解决爬楼梯问题有四种解法,各有优劣。递归解法直观但效率低;缓存递归结果可以提高效率;自下而上的解法更直接;而优化后的自下而上解法空间复杂度最低。在面试中,掌握第四种解法将让你脱颖而出,展示你的算法基础和优化思维。