题目
My way
很简单的二维dp思路,每一层的元素依赖于上一层同列元素和上一层前一列元素。
二维DP
状态定义:
\[ \begin{align*} & i:\ 行号 \\ & j:\ 列号 \\ & triangle[i][j]:\ 原始三角形上的i行,\ j列的数字 \\ & dp[i][j]:\ dp数组的i行,\ j列上的数字 \\ & 0 <= i == j <= n, n为行数 \end{align*} \]
状态转移方程:
\[ dp[i][j] = triangle[i][j] + min\{dp[i-1][j-1],\ dp[i-1][j] \} \]
Base case:
\[ dp[i][j] = triangle[i][j],\ \text{if $i == 0$ and $j == 0$} \]
Corner case:
\[ dp[i][j] = triangle[i][j] + dp[i-1][j],\ \text{if $j == 0$} \\ dp[i][j] = triangle[i][j] + dp[i-1][j-1],\ \text{if $i == j$} \]
C++实现
1 | class Solution { |
一维DP
如何仅使用\(O(n)\)大小的额外空间呢?
因为每一行的状态仅依赖于上一行的状态,故可将二维DP to 一维DP.
对空间复杂度进行优化。
状态定义:
\[ \begin{align*} & i:\ 行号 \\ & j:\ 列号 \\ & triangle[i][j]:\ 原始三角形上的i行,\ j列的数字 \\ & dp[k]:\ dp数组的第k个数字 \\ & 0 <= j <= i <= k == n, n为行数 \\ \end{align*} \]
状态转移方程:
\[ dp[j] = triangle[i][j] + min\{dp[j-1], dp[j]\} \]
Base case:
\[ dp[j] = triangle[i][j],\ \text{if $i == 0$ and $j == 0$} \]
Corner case:
\[ dp[j] = triangle[i][j] + dp[j],\ \text{if $j == 0$} \\ dp[j] = triangle[i][j] + dp[j-1],\ \text{if $i == j$} \]
C++实现
1 | class Solution { |
Elon way
关键能有这个思路上的转变:
自顶向下最短距离 <=> 自底向上最短距离
自顶向下, 记忆化搜索
- 思路类似上面 二维DP。
- 还利用了树的遍历思维解决问题
1 | class Solution { |
自底向上, DP
1 | public int minimumTotal(List<List<Integer>> triangle) { |
总结
- 这里的自顶向下,自底向上 感觉就是我之前所理解的二维DP。不过我是采用非递归方式实现的,而这里是递归方式实现的。
- *思考题目后,思路上的转变:
- 自顶向下最短距离 <=> 自底向上最短距离
- 以及多多尝试 递归方式实现此类DP。