剑指 Offer 47. 礼物的最大价值
题目:
思路:
【1】碰到的时候最先想起的是深度优先和广度优先的遍历(后面发现了要用到辅助空间,那么用到辅助空间的话,其实还可以考虑动态规划)
【2】动态规划的方式(但其实这种相对更优,可能是由于空间换了时间)
代码展示:
动态规划的方式:
//时间2 ms击败97.82% //内存43.8 MB击败89.68% //时间复杂度 O(MN) : M,N 分别为矩阵行高、列宽;动态规划需遍历整个 grid 矩阵,使用 O(MN) 时间。 //空间复杂度 O(MN) : 开辟了等大小的额外空间。 class Solution { public int maxValue(int[][] grid) { int row = grid.length; int column = grid[0].length; //dp[i][j]表示从grid[0][0]到grid[i - 1][j - 1]时的最大价值 int[][] dp = new int[row + 1][column + 1]; for (int i = 1; i <= row; i++) { for (int j = 1; j <= column; j++) { dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]) + grid[i - 1][j - 1]; } } return dp[row][column]; } } 当然还存在不开辟额外空间 //时间2 ms击败97.82% //内存43.8 MB击败88.31% //时间复杂度 O(MN) : M,N 分别为矩阵行高、列宽;动态规划需遍历整个 grid 矩阵,使用 O(MN) 时间。 //空间复杂度 O(1) : 原地修改使用常数大小的额外空间。 class Solution { public int maxValue(int[][] grid) { int m = grid.length, n = grid[0].length; // 初始化第一行 for(int j = 1; j < n; j++){ grid[0][j] += grid[0][j - 1]; } // 初始化第一列 for(int i = 1; i < m; i++) { grid[i][0] += grid[i - 1][0]; } for(int i = 1; i < m; i++){ for(int j = 1; j < n; j++){ grid[i][j] += Math.max(grid[i][j - 1], grid[i - 1][j]); } } return grid[m - 1][n - 1]; } }
深度优先遍历的方式:
//但是这种直接是超时,估计是出现数据庞大的时候,重复运算多了耗时比较多 class Solution { public int maxValue(int[][] grid) { if (grid == null || grid.length == 0){ return 0; } return dfsmaxValue(grid,grid.length-1,grid[0].length-1); } //i为行,j为列,该方式为从终点反推回起点 public int dfsmaxValue(int[][] grid,int i,int j){ if (i < 0 || j < 0){ return 0; } //向上走 与 向左走 之前取最大值 return Math.max(dfsmaxValue(grid, i - 1, j), dfsmaxValue(grid, i, j - 1)) + grid[i][j]; } } //开辟一块空间保存一下计算的值 //时间20 ms击败2.20% //内存46.5 MB击败5.6% class Solution { public int maxValue(int[][] grid) { if (grid == null || grid.length == 0){ return 0; } return dfsmaxValue(grid,grid.length-1,grid[0].length-1, new HashMap<>()); } //i为行,j为列,该方式为从终点反推回起点 public int dfsmaxValue(int[][] grid,int i,int j, Map<String, Integer> map){ if (i < 0 || j < 0){ return 0; } String key = i + "*" + j; int res = map.getOrDefault(key, -1); //如果以前计算过,就从map中取 if (res != -1){ return res; } //如果之前没有计算过,则进行计算 res = Math.max(dfsmaxValue(grid, i - 1, j, map), dfsmaxValue(grid, i, j - 1, map)) + grid[i][j]; //把计算的结果还存到map中 map.put(key, res); return res; } }