返回
LeetCode 三角形最小路径和:O(n) 空间复杂度的巧妙解法
见解分享
2023-09-29 23:50:38
前言
在探索计算机科学算法的迷人世界时,我们经常会遇到一些优雅而高效的解法,它们巧妙地利用了问题的特定特性来节省空间或时间。LeetCode 120 三角形最小路径和问题就是这样一个引人注目的例子,它挑战我们找到从三角形的顶部到底部的一条路径,使得沿途数字之和最小。
问题
给定一个三角形,其中每个节点包含一个整数,找到从三角形的顶部到任意底层节点的一条路径,使得沿途数字之和最小。每一步,你可以移动到同一层相邻的两个节点之一。
例如,对于如下三角形:
2
3 4
6 5 7
4 1 8 3
最小路径和为 11,即 2 + 3 + 5 + 1。
传统解法:自顶向下,O(2^n) 空间复杂度
最直接的解法是采用自顶向下的递归方法。在每个节点,我们计算向左和向右移动的最小路径和,然后返回较小的一个。这个解法虽然简单明了,但空间复杂度为 O(2^n),其中 n 是三角形的层数。这是因为在递归调用过程中,为每个可能的路径都创建了一个新的栈帧。
O(n) 空间复杂度解法:自底向上,动态规划
为了优化空间复杂度,我们可以采用自底向上的动态规划方法。这个方法从三角形的底部开始,逐渐向上累加最小路径和。具体步骤如下:
- 初始化 :将三角形的底部层作为备忘录,存储每个节点的最小路径和。
- 递推 :对于第 i 层的每个节点,计算它的最小路径和,即当前节点的值加上前一层的左右节点的最小路径和中较小的一个。更新备忘录。
- 向上递推 :重复步骤 2,直到到达三角形的顶部。
通过这种方法,我们只存储当前层和前一层的备忘录,从而将空间复杂度降低到 O(n)。
备忘录优化
为了进一步优化空间复杂度,我们可以观察到在计算第 i 层节点的最小路径和时,我们只需要前一层的备忘录中相邻的两个节点。因此,我们可以使用一个滑动窗口来维护前一层的备忘录,从而将空间复杂度进一步降低到 O(1)。
代码示例
以下是使用动态规划和备忘录优化的 Python 代码示例:
def minimum_total(triangle):
n = len(triangle)
# 初始化备忘录
memo = triangle[-1]
# 自底向上递推
for i in range(n - 2, -1, -1):
# 滑动窗口维护备忘录
for j in range(i + 1):
memo[j] = triangle[i][j] + min(memo[j], memo[j + 1])
return memo[0]
结论
LeetCode 三角形最小路径和问题是一个经典的算法问题,展示了动态规划和备忘录优化技术的强大功能。通过采用自底向上的方法和滑动窗口备忘录,我们可以以 O(n) 的空间复杂度高效求解这个问题,为我们提供了解决此类问题的通用框架。