2020.7.14 力扣每日
方法一:
1 class Solution { 2 public int minimumTotal(List<List<Integer>> triangle) { 3 int res = Integer.MAX_VALUE; 4 int height = triangle.size(); 5 if(height <= 1) 6 return triangle.get(0).get(0); 7 int[] dp = new int [(height+1) * height / 2]; 8 dp[0] = triangle.get(0).get(0); 9 int index = 1; 10 for (int i = 1; i < height; i++) { 11 for(int j = 0; j < triangle.get(i).size(); j++) { 12 int a; 13 if(j == 0) 14 a = dp[index - i]; 15 else if(j == i ) 16 a = dp[index - i -1]; 17 else a = dp[index - i -1] >= dp[index - i] ? dp[index - i] : dp[index - i -1]; 18 dp[index] = a + triangle.get(i).get(j); 19 index++; 20 } 21 } 22 for(int j = 0; j < height; j++) { 23 if(dp[index - 1 - j] <= res) 24 res = dp[index - 1 - j]; 25 } 26 return res; 27 } 28 }
解题思路:
本题使用动态规划的方法,创建了dp数组存取每个点的最小路径和,此处可以创建数组dp[height][height],存取对应点,代码可读性更强,但会有多余的空间;也可创建数组dp[height*(height+1)/2],没有多余空间,此处采用了第二种方法。遍历每行的元素时,最小路径和就为上一行对应的dp[index-i]与dp[inxe-i-1]中的较小值,加上当前位置元素的值。
注意点:
每行的第一个与最后个元素的dp值需要特殊处理。
空间复杂度:O(N^2) N为三角形高度height
时间复杂度:O(N^2)
题后总结:
优:熟练使用了动态规划解决问题,对于特殊情况的考虑充分
差:空间复杂度仍可优化,代码也可使用Math.min进行简化
方法二:
优化:考虑到每行的dp值实际上只和上一行的dp值相关,可以设置dp[height]存储上一行最小值的情况,进行空间复杂度的优化。同时也可采取从最后行开始,反向计算dp值,这样就无需再次遍历dp数组寻找最小值了。
注意点:
如果采用从上往下遍历时,由于dp[j]的值与dp[j-1]和dp[j]有关,如果每行从左往右遍历,那会造成dp[j-1]数据的变更,导致结果出错,所以需要从右往左遍历;
采用从下往上遍历的顺序时,则相反,dp[j]与dp[j],dp[j+1]有关,就需要从左往右遍历
1 public int minimumTotal(List<List<Integer>> triangle) { 2 int height = triangle.size(); 3 if(height <= 1) 4 return triangle.get(0).get(0); 5 int[] dp = new int [height]; 6 for (int i = height - 1; i >= 0; i--) 7 dp[i] = triangle.get(height - 1).get(i); 8 for (int i = height - 2; i >= 0; i--) { 9 for (int j = 0; j <= i; j++) { 10 dp[j] = Math.min(dp[j], dp[j + 1]) + triangle.get(i).get(j); 11 } 12 } 13 return dp[0]; 14 }
空间复杂度:O(N) N为三角形高度height
时间复杂度:O(N^2)