您的位置:首页 > Web前端

LeetCode.64 Minimum Path Sum && 剑指Offer_47 最大礼物价值 (经典DP问题,***必备题***)

2017-10-18 20:08 471 查看
题目:
Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path.Note: You can only move either down or right at any point in time.
分析:class Solution {
public int minPathSum(int[][] grid) {
//从左上角到右下角,给出路径权值最小的路径
//类似triangle求最小路径,但是这里规定了起点和终点
int [][] cur=grid;
//最左边和最上边赋值

for (int i = 1; i < grid[0].length; i++) {
//上边
cur[0][i]+=cur[0][i-1];
}

for (int i = 1; i < grid.length; i++) {
//左边
cur[i][0]+=cur[i-1][0];
}

for(int i=1;i<grid.length;i++){
//动态规划三要素:问题的阶段,每个阶段的状态以及从前一个阶段转化到后一个阶段之间的递推关系
for(int j=1;j<grid[i].length;j++){
//递推关系
cur[i][j]=Math.min(cur[i-1][j],cur[i][j-1])+grid[i][j];
}
}
return cur[grid.length-1][grid[0].length-1];
}
}改进版:(因此i-2行及更上面的不需要保存下来,我们可以用一个一维数组来替代前面的二位矩阵)class Solution {
public int minPathSum(int[][] grid) {
int row=grid.length;
int col=grid[0].length;
int [] dp=new int[col];
for(int i=0;i<row;i++){
if(i==0){
//第一行
for(int j=0;j<col;j++){
if(j==0){
dp[j]=grid[i][0];
}else{
dp[j]=dp[j-1]+grid[i][j];
}
}
}else{
for(int j=0;j<col;j++){
if(j==0){
dp[j]=dp[j]+grid[i][j];
}else{
dp[j]=Math.min(dp[j-1],dp[j])+grid[i][j];
}
}
}
}

return dp[col-1];
}
}

剑指Offer_47 最大礼物路径之和,和上面类似,求最大的路径之和。
分析: //给定m*n的矩阵,每个坐标内有一个礼物价值,从左上角到右下的路径中(每次只能向下或者向右移动),可以求得最大的礼物价值和是多少?
//思路:类似机器人从左上角到右下角的路径和类似。使用一个一维数组记录每次到该坐标的最大值
public static void main(String[] args) {
int [][] grifts={{1,10,3,8},{12,2,9,6},{5,7,4,11},{3,7,16,5}};
System.out.println(getValue(grifts));
}
public static int getValue(int [][] grifts){
//书中原创版本
// int m=grifts.length;
// int n=grifts[0].length;
//
// int [] dp = new int
;
// for(int i=0;i<m;i++){
// for(int j=0;j<n;j++){
// //上面、左边过来的最大值
// int up=0;
// int left=0;
//
// if(i>0){
// up=dp[j];
// }
// if(j>0){
// left=dp[j-1];
// }
//
// //每次更新该值
// dp[j]=Math.max(up,left)+grifts[i][j];
//
// }
// }
// return dp[n-1];

//自己理解版本,先计算最上面一行,之后计算最左边一列
//采用一维数组记录
int row=grifts.length;
int col=grifts[0].length;
int [] dp=new int[col];
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
if(i==0){
if(j==0){
//第一行的第一个
dp[j]=grifts[i][j];
}else {
//第一行的,后面几个
dp[j] = dp[j - 1] + grifts[i][j];
}
}else{
if(j==0){
//某行的第一个,只能从上面上来
dp[j]=dp[j]+grifts[i][j];
}else{
//除了最上面一行和最左边的一列,中间的位置
dp[j]=Math.min(dp[j],dp[j-1])+grifts[i][j];
}

}
}
}
return dp[col-1];
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: