Question
Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below.
For example, given the following triangle
[
[2],
[3,4],
[6,5,7],
[4,1,8,3]
]
The minimum path sum from top to bottom is 11 (i.e., 2 + 3 + 5 + 1 = 11).
Note:
- Bonus point if you are able to do this using only O(n) extra space, where n is the total number of rows in the triangle.
问题解析:
给定三角形二维列表,求出从顶到底的和最小的路径,每步只能在下一行的相邻两元素中选取。
Answer
Solution 1:
DP。
- 由题目可以看出,其中每一步均由上一步的问题构成,所以利用动态规划来求解。
- 由题目条件限定,要求只能在相邻元素中选取,观察可知,如本行取
j
,则下一行在j
和j+1
中选取; - 构建动态规划数组,保存前一行和当前行符合题目要求的路径和,以自底向上的方式,最终归一到第
0
行的0
元素位置。那么动态规划数组的第0
个元素即为最小路径和。
class Solution {
public int minimumTotal(List<List<Integer>> triangle) {
int[] res = new int[triangle.size()+1];
for (int i = triangle.size()-1; i >= 0; i--){
for (int j = 0; j < triangle.get(i).size(); j++){
res[j] = Math.min(res[j], res[j+1]) + triangle.get(i).get(j);
}
}
return res[0];
}
}
- 时间复杂度:O(n^2),空间复杂度:O(n)
Solution 2:
Solution 1 的空间复杂度优化。
- 通过观察可以知道,因为最终的和保存在动态规划数组的首位,我们可以直接将选取出的路径和加到triangle的前一行中,故无需构建新的动态规划数组。
- 但由于需要修改triangle列表,需要set操作,相比解法一,减少了空间复杂度,却增加了时间复杂度;
class Solution {
public int minimumTotal(List<List<Integer>> triangle) {
for (int i = triangle.size()-2; i >= 0; i--){
for (int j = 0; j < triangle.get(i).size(); j++){
triangle.get(i).set(j, triangle.get(i).get(j) + Math.min(triangle.get(i + 1).get(j), triangle.get(i + 1).get(j + 1)));
}
}
return triangle.get(0).get(0);
}
}
- 时间复杂度:O(n^2) * O(set()),空间复杂度:O(1)
Solution 3:
python 解法,DP,与解法一相同。
为了加强对Python的练习,以后的练习中都会Python的程序。
class Solution:
def minimumTotal(self, triangle):
"""
:type triangle: List[List[int]]
:rtype: int
"""
if not triangle:
return
res = triangle[-1]
for i in range(len(triangle)-2, -1, -1):
for j in range(len(triangle[i])):
res[j] = min(res[j], res[j+1]) + triangle[i][j]
return res[0]