题目描述
- 一眼动态规划啦~
思路 && 代码
1. 常规动规 O(n2n^2n2) 、O(n2n^2n2)
- dp[i][j]: 对应位置 grid[i - 1][j - 1] 为终点,可得到的最多礼物
- dp[][] 外包围一层,省去边界判断~
- 核心思想:从左边、上边选择最大值即可
class Solution {public int maxValue(int[][] grid) {int m = grid.length;int n = grid[0].length;int[][] dp = new int[m + 1][n + 1];for(int i = 1; i <= m; i++) {for(int j = 1; j <= n; j++) {dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);dp[i][j] += grid[i - 1][j - 1];}}return dp[m][n];}
}
2. 滚动数组法 O(n2n^2n2) 、O(nnn)
- 通过滚动数组的方法,可以节约空间复杂度!
- 时间复杂度是不变的~
- 之所以可以使用滚动数组的方法,是因为维护当前行,只需要前一行的值,而与再往前的行数无关
class Solution {public int maxValue(int[][] grid) {int m = grid.length;int n = grid[0].length;int[] dp = new int[n + 1];for(int i = 1; i <= m; i++) {for(int j = 1; j <= n; j++) {dp[j] = Math.max(dp[j - 1], dp[j]);dp[j] += grid[i - 1][j - 1];}}return dp[n];}
}
原地操作O(n2n^2n2) 、O(111)
class Solution {public int maxValue(int[][] grid) {for(int i = 0; i < grid.length; i++) {for(int j = 0; j < grid[0].length; j++) {int top = i > 0 ? grid[i - 1][j] : 0;int left = j > 0 ? grid[i][j - 1] : 0;grid[i][j] += Math.max(top, left);}}return grid[grid.length - 1][grid[0].length - 1];}
}