题目描述
- 一眼动态规划啦~
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/da7e1f954281088d03900f96e963e5eb.png)
思路 && 代码
1. 常规动规 O(
n
2
n^2
n2) 、O(
n
2
n^2
n2)
- 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(
n
2
n^2
n2) 、O(
n
n
n)
- 通过滚动数组的方法,可以节约空间复杂度!
- 时间复杂度是不变的~
- 之所以可以使用滚动数组的方法,是因为维护当前行,只需要前一行的值,而与再往前的行数无关
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(
n
2
n^2
n2) 、O(
1
1
1)
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];
}
}