题目描述:
给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。
例如,给定三角形:
[
[2],
[3,4],
[6,5,7],
[4,1,8,3]
]
自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。
说明:
如果你可以只使用 O(n) 的额外空间(n 为三角形的总行数)来解决这个问题,那么你的算法会很加分。
原题地址:https://leetcode-cn.com/problems/triangle/submissions/
题目思路:
这道题可以用递归(回溯)解答,但是时间复杂度是O(a^n),若是采用动态递归的话,时间复杂度只需要O(m*n),空间复杂度由O(m*n)还可以优化成O(n)。
dp[][]设置成2维的,和triangle维度一样,刚开始先初始化最后一行,和triangle最后一行一样。
转移方程:
dp[i][j] = min{dp[i+1][j], dp[i+1][j+1]} + triangle[i][j]
这个其实也可以优化,我们把行省略,dp设置成1维的,因为每个值只依赖当前值和它右侧的一个值,这样从左到右遍历的时候,就可以覆盖上一次的值了,不会影响最后结果。
dp[j] = min{dp[j], dp[j+1]} + triangle[i][j]
题目代码:
解法1:空间复杂度是O(m*n)。
public int minimumTotal(List<List<Integer>> triangle) { Integer[][] dp = new Integer[triangle.size()][triangle.get(triangle.size() - 1).size()]; //初始化 for (int i = 0; i < dp[0].length; i++) { dp[dp.length - 1][i] = triangle.get(dp.length - 1).get(i); } //状态转移方程 for (int i = triangle.size() - 2; i >= 0; i--) { for (int j = 0; j < triangle.get(i).size(); j++) { dp[i][j] = Integer.min(dp[i + 1][j], dp[i + 1][j + 1]) + triangle.get(i).get(j); } } return dp[0][0]; }
解法2:空间复杂度是O(n)。
public int minimumTotal(List<List<Integer>> triangle) { Integer[] dp = new Integer[triangle.size()]; //初始化 for (int i = 0; i < dp.length; i++) { dp[i] = triangle.get(triangle.size() - 1).get(i); } //状态转移方程 for (int i = triangle.size() - 2; i >= 0; i--) { for (int j = 0; j < triangle.get(i).size(); j++) { dp[j] = Integer.min(dp[j], dp[j + 1]) + triangle.get(i).get(j); } } return dp[0]; }