NO.120 三角形最小路径和 中等
思路一:动态规划 dp[i][j]含义:到triangle[i][j]元素为止的最小路径和。
初始化:dp[0][0]=triangle[0][0],因为第一行只有一个元素。
状态转移:所以dp[i][j]=min(dp[i-1][j]+d[i-1][j-1])+triangle[i][j]
,需要注意特殊情况:j==0没有j-1、j==i没有j。
最后取出dp数组的最后一行,从中找出最小的路径和。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| public int minimumTotal(List<List<Integer>> triangle) { if (triangle == null || triangle.size() == 0) return 0; int r = triangle.size(); int c = triangle.get(r - 1).size(); int[][] dp = new int[r][c]; dp[0][0] = triangle.get(0).get(0); for (int i = 1; i < r; i++) { List<Integer> row = triangle.get(i); for (int j = 0; j <= i; j++) { if (j == 0) { dp[i][j] = dp[i - 1][j] + triangle.get(i).get(j); } else if (j == i) { dp[i][j] = dp[i - 1][j - 1] + triangle.get(i).get(j); } else { dp[i][j] = Math.min(dp[i - 1][j - 1], dp[i - 1][j]) + triangle.get(i).get(j); } } } int ans = Integer.MAX_VALUE; for (int e : dp[r - 1]) { ans = Math.min(ans, e); } return ans; }
|
时间复杂度:O(r^2) 空间复杂度:O(r^2)
优化空间到O(r) 每次填写一下层的时候,只关心dp[i - 1][j]
和dp[i - 1][j - 1]
用两个变量right、left记录上一层的这两个值。
dp数组初始化为[r]大小,状态转移方程不变,复用这个一维dp数组。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| public int minimumTotal(List<List<Integer>> triangle) { if (triangle == null || triangle.size() == 0) return 0; int r = triangle.size(); int[] dp = new int[r]; dp[0] = triangle.get(0).get(0); int left = 0, right; for (int i = 1; i < r; i++) { List<Integer> row = triangle.get(i); for (int j = 0; j <= i; j++) { right = dp[j]; if (j == 0) { dp[j] = right + row.get(j); } else if (j == i) { dp[j] = left + row.get(j); } else { dp[j] = Math.min(left, right) + row.get(j); } left = right; } } int ans = Integer.MAX_VALUE; for (int e : dp) { ans = Math.min(ans, e); } return ans; }
|
时间复杂度:O(r^2) 空间复杂度:O(r)
自底向上DP 从下向上找最小路径,最终找到最上层的一个元素,得到最小路径和。
可以免除边界判断,不需要记录上一层的两个变量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public int minimumTotal(List<List<Integer>> triangle) { if (triangle == null || triangle.size() == 0) return 0; int r = triangle.size(); int[] dp = new int[r + 1]; for (int i = r - 1; i >= 0; i--) { List<Integer> row = triangle.get(i); for (int j = 0; j <= i; j++) { dp[j] = Math.min(dp[j], dp[j + 1]) + row.get(j); } } return dp[0]; }
|
时间复杂度:O(r^2) 空间复杂度:O(r)
本人菜鸟,有错误请告知,感激不尽!
更多题解和源码:github