参考资料:《剑指Offer》
53. Maximum Subarray
Given an integer array nums, find the subarray with the largest sum, and return its sum.
Example 1:
Input: nums = [-2,1,-3,4,-1,2,1,-5,4]
Output: 6
Explanation: The subarray [4,-1,2,1] has the largest sum 6.
思路:
计算 以nums[i]为结尾时的子串的 maxSum 作为 local optimum, 然后 对i=0,1,…,n-1, 取 local optimum的最大值即可。
那么 如何求 local optimum,即 以nums[i]为结尾时的子串的 maxSum, 呢?
答:分两种情况:1. nums[i] 自己做 subArray; 2. nums[i] 联合 nums[i-1]的最优解一起 做 subArray; 对这两种情况取最大即可。
class Solution {
public int maxSubArray(int[] nums) {
int dp=nums[0]; // dp[0]
int ans=dp;
for(int i=1;i<nums.length;i++)
{
dp = Math.max(nums[i],nums[i]+dp);
ans = Math.max(ans,dp);
}
return ans;
}
}
【剑指】礼物最大价值
在一个 m*n 的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一格、直到到达棋盘的右下角。给定一个棋盘及其上面的礼物的价值,请计算你最多能拿到多少价值的礼物?
示例 1:
输入:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
输出: 12
解释: 路径 1→3→5→2→1 可以拿到最多价值的礼物
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/li-wu-de-zui-da-jie-zhi-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:很像二维的楼梯问题,
对于一般位置(i,j)而言,他可能从(i-1,j)或(i,j-1)来到这里。
dp[i][j]表示 从(0,0)到(i,j) 所获的最大收益。
注意:初始化dp表的第0行和第0列。
class Solution {
public int maxValue(int[][] grid) {
int m = grid.length;
int n = grid[0].length;
int[][] dp = new int[m][n];
dp[0][0] = grid[0][0];
for(int i=1;i<m;i++)
{
dp[i][0] = dp[i-1][0]+grid[i][0];
}
for(int j=1;j<n;j++)
{
dp[0][j] = dp[0][j-1]+grid[0][j];
}
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])+grid[i][j];
}
}
return dp[m-1][n-1];
}
}
空间压缩
一行一行地更新dp表
public int maxValue(int[][] grid) {
int m = grid.length;
int n = grid[0].length;
int[] dp = new int[n];
dp[0]=grid[0][0];
for(int i=1;i<n;i++)
{
dp[i] = grid[0][i]+dp[i-1];
}
for(int i=1;i<m;i++)
{
dp[0]=grid[i][0]+dp[0];
for(int j=1;j<n;j++)
{
dp[j] = Math.max(dp[j-1],dp[j])+grid[i][j];
}
}
return dp[n-1];
}