官方链接
https://leetcode-cn.com/problems/triangle
给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。
例如,给定三角形:
[
[2],
[3,4],
[6,5,7],
[4,1,8,3]
]
自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。
说明:
如果你可以只使用 O(n) 的额外空间(n 为三角形的总行数)来解决这个问题,那么你的算法会很加分。
思路
- brute-force, 递归, n 层: left or right: O(2^n)
traverse(i, j) {
traverse(i+1, j)
traverse(i+1, j+1)
}
- DP
- a. 重复性(分治) problem(i, j) = min(sub(i+1, j) sub(i+1, j+1)) + a[i,j]
- b. 定义状态数组: f[i,j]
- c. DP 方程: f[i,j] = min(f[i+1, j], f[i+1, j+1]) + a[i,j]
参考链接
解法一
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, Math.min(triangle.get(i+1).get(j), triangle.get(i+1).get(j+1)) + triangle.get(i).get(j));
}
}
return triangle.get(0).get(0);
}
}
class Solution:
def minimumTotal(self, triangle: List[List[int]]) -> int:
'''
dp[i][j] = triangle[i][j] + min(dp[i+1][j]+dp[i+1][j+1])
'''
mini,M = triangle[-1], len(triangle)
for i in range(M-2, -1, -1):
for j in range(len(triangle[i])):
mini[j] = triangle[i][j] + min(mini[j], mini[j+1])
return mini[0]
class Solution:
def minimumTotal(self, triangle: List[List[int]]) -> int:
'''
dp[i][j] = triangle[i][j] + min(dp[i+1][j]+dp[i+1][j+1])
'''
dp = triangle
M = len(triangle)
for i in range(M-2, -1, -1):
for j in range(len(triangle[i])):
dp[i][j] += min(dp[i+1][j], dp[i+1][j+1])
return dp[0][0]
class Solution:
def minimumTotal(self, triangle: List[List[int]]) -> int:
f = [0] * (len(triangle) + 1)
for row in triangle[::-1]:
for i in range(len(row)):
f[i] = row[i] + min(f[i], f[i + 1])
return f[0]
class Solution {
public:
int minimumTotal(vector<vector<int>>& triangle) {
for (int i = triangle.size() - 2; i >= 0; i--) {
for (int j = 0; j < triangle[i].size(); j++) {
triangle[i][j] += min(triangle[i+1][j], triangle[i+1][j+1]);
}
}
return triangle[0][0];
}
};
解法二
递归
class Solution {
public int minimumTotal(List<List<Integer>> triangle) {
int size = triangle.size();
Integer[][] mem = new Integer[size][size];
return helper(mem, 0, 0, triangle);
}
private int helper(Integer[][]mem, int level, int c, List<List<Integer>> triangle) {
if(mem[level][c] != null) return mem[level][c];
if (level == triangle.size() - 1) return triangle.get(level).get(c);
int left = helper(mem, level + 1, c, triangle);
int right = helper(mem,level + 1, c + 1, triangle);
return mem[level][c] = Math.min(left, right) + triangle.get(level).get(c);
}
}
解法二
dfs
class Solution {
int minSum = 0;
public int minimumTotal(List<List<Integer>> triangle) {
if (triangle.size() == 0 || triangle.get(0).size() == 0) return 0;
return dfs(triangle, 0, 0, "", 0);
}
private int dfs(List<List<Integer>> triangle, int i, int j, String path, int sum) {
// terminator
if (i == triangle.size() - 1) {
path += triangle.get(i).get(j) + " # ";
sum += triangle.get(i).get(j);
System.out.println(path + " with sum: " + sum);
return 0;
}
// process
path += triangle.get(i).get(j) + " -> ";
sum += triangle.get(i).get(j);
// drill down
dfs(triangle, i + 1, j, path, sum);
dfs(triangle, i + 1, j + 1, path, sum);
// clear
// Note: no need to clear up the state `path`
return 0;
}
}