LeetCode 64. Minimum Path Sum

题目

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.

Example:

Input:
[
  [1,3,1],
  [1,5,1],
  [4,2,1]
]
Output: 7
Explanation: Because the path 1→3→1→1→1 minimizes the sum.

亚麻OA基础版。这道题要求从一个二维数组从左上到右下的路径中的最少之和,每次只能往右或者往下走。这道题的做法应该是DP,但我也有考虑过DFS、BFS之类的,不知道是不是想偏了。如果用二维DP做的话非常简单,先把第一行和第一列给定义好,然后剩下的元素就取dp[i][j] = min(dp[i - 1][j], dp[i][j - 1])并加上当前的grid值即可。代码写起来还是非常简单的,时空复杂度都是O(n^2)

C++:运行时间12ms,45.24%,空间10.9M,42.1%:

class Solution {
public:
    int minPathSum(vector<vector<int>>& grid) {
        int rows = grid.size();
        int cols = grid[0].size();
        vector<vector<int>> dp(rows, vector<int>(cols, grid[0][0]));
        for (int i = 1; i < rows; i++) {
            dp[i][0] = dp[i - 1][0] + grid[i][0];
        }
        for (int j = 1; j < cols; j++) {
            dp[0][j] = dp[0][j - 1] + grid[0][j];
        }
        for (int i = 1; i < rows; i++) {
            for (int j = 1; j < cols; j++) {
                dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j];
            }
        }
        return dp[rows - 1][cols - 1];
    }
};

这里还学会了二维vector初始化的方法:vector<vector<int>> dp(rows, vector<int>(cols, grid[0][0]));

2020.8.18补Java:

Runtime: 3 ms, faster than 47.06% of Java online submissions for Minimum Path Sum.

Memory Usage: 43.7 MB, less than 8.50% of Java online submissions for Minimum Path Sum.

class Solution {
    public int minPathSum(int[][] grid) {
        int rows = grid.length;
        int cols = grid[0].length;
        int[][] dp = new int[rows][cols];
        dp[0][0] = grid[0][0];
        for (int i = 1; i < cols; i++) {
            dp[0][i] = dp[0][i - 1] + grid[0][i];
        }
        for (int i = 1; i < rows; i++) {
            dp[i][0] = dp[i - 1][0] + grid[i][0];
        }
        for (int i = 1; i < rows; i++) {
            for (int j = 1; j < cols; j++) {
                dp[i][j] = Math.min(dp[i - 1][j] + grid[i][j], 
                                    dp[i][j - 1] + grid[i][j]);
            }
        }
        return dp[rows - 1][cols - 1];
    }
}

看了discussion发现上面的二维数组还可以优化空间复杂度,只需要用到O(n)。因为每次更新dp[i][j]的时候,我们只需要拥有它左边的那个元素和它上方的元素。因此,我们可以只定义一个vector用来存当前遍历的这一列,每次更新的时候根据上次的更新第一行,后面的就跟它左边和上面的元素进行比较即可(但是这里之前浪费了好长时间不太知道该怎么写)。时间8ms,87.52%,空间10.2M,100%:

class Solution {
public:
    int minPathSum(vector<vector<int>>& grid) {
        int rows = grid.size();
        int cols = grid[0].size();
        vector<int> curr(rows, grid[0][0]);
        for (int i = 1; i < rows; i++) {
            curr[i] = curr[i - 1] + grid[i][0];
        }
        for (int j = 1; j < cols; j++) {
            curr[0] += grid[0][j];
            for (int i = 1; i < rows; i++) {
                curr[i] = min(curr[i - 1], curr[i]) + grid[i][j];
            }
        }
        return curr[rows - 1];
    }
};

2020.8.18补Java:不知道为啥去年说不知道该怎么写,这次倒是看完优化思路以后马上就写出来了,但是有一个小坑卡了一下下,就是那个双重循环里的i和j的顺序问题。

Runtime: 4 ms, faster than 25.99% of Java online submissions for Minimum Path Sum.

Memory Usage: 43 MB, less than 34.28% of Java online submissions for Minimum Path Sum.

class Solution {
    public int minPathSum(int[][] grid) {
        int rows = grid.length;
        int cols = grid[0].length;
        int[] dp = new int[rows];
        dp[0] = grid[0][0];
        for (int i = 1; i < rows; i++) {
            dp[i] = dp[i - 1] + grid[i][0];
        }
        for (int i = 1; i < cols; i++) {
            for (int j = 0; j < rows; j++) {
                if (j == 0) {
                    dp[j] += grid[j][i];
                } else {
                    dp[j] = Math.min(dp[j - 1] + grid[j][i],
                                     dp[j] + grid[j][i]);
                }
            }
        }
        return dp[rows - 1];
    }
}

对于亚麻那道题:https://leetcode.com/discuss/interview-question/383669/

Given a matrix with r rows and c columns, find the maximum score of a path starting at [0, 0] and ending at [r-1, c-1]. The score of a path is the minimum value in that path. For example, the score of the path 8 → 4 → 5 → 9 is 4.

Don't include the first or final entry. You can only move either down or right at any point in time.

Example 1:

Input:
[[5, 1],
 [4, 5]]

Output: 4
Explanation:
Possible paths:
5 → 1 → 5 => min value is 1
5 → 4 → 5 => min value is 4
Return the max value among minimum values => max(4, 1) = 4.

Example 2:

Input:
[[1, 2, 3]
 [4, 5, 1]]

Output: 4
Explanation:
Possible paths:
1-> 2 -> 3 -> 1
1-> 2 -> 5 -> 1
1-> 4 -> 5 -> 1
So min of all the paths = [2, 2, 4]. Note that we don't include the first and final entry.
Return the max of that, so 4.

亚麻这道题要求的是,一个path的score定义为这个path里最小的值,要求所有path的score里的最大的,题目比较绕。还是采用类似的DP的方法,先把第一行和第一列给赋值好,然后对后面的dp[i][j],状态转移方程采用:dp[i][j] = max(min(dp[i - 1][j], grid[i][j]), min(dp[i][j - 1], grid[i][j])),相当于就是一个dp二维矩阵中的元素,采用到它的两个路径中上一个节点和它自己比较的较小值(也就是到这一个元素的score)中的较大的(也就是更大的score),另外注意第一个节点和最后一个节点是不算数的,因此要特殊处理一下。代码:

// Given a matrix with r rows and c columns, find the maximum score of a path starting at [0, 0] and ending at [r - 1, c - 1]. The score of a path is the minimum value in that path. For example, the score of the path 8 → 4 → 5 → 9 is 4.

#include <iostream>
#include <string>
#include <vector>
#include <limits.h>
using namespace std;

int maxScore(vector<vector<int> >& grid){
    int rows = grid.size();
    int cols = grid[0].size();
    vector<vector<int>> dp(rows, vector<int>(cols, grid[0][0]));
    dp[0][1] = grid[0][1];
    dp[1][0] = grid[1][0];
    for (int i = 2; i < rows; i++) {
        dp[i][0] = min(dp[i - 1][0], grid[i][0]);
    }
    for (int i = 2; i < cols; i++) {
        dp[0][i] = min(dp[0][i - 1], grid[0][i]);
    }
    
    for (int i = 1; i < rows; i++) {
        for (int j = 1; j < cols; j++) {
            if (!((i == rows - 1) && (j == cols - 1))) {
                dp[i][j] = max(min(grid[i][j], dp[i - 1][j]), min(grid[i][j], dp[i][j - 1]));
            }
            else {
                dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
            }
        }
    }
    return dp[rows - 1][cols - 1];
    //return 0;
}

int main()
{
    // Testing
    vector<vector<int>> grid1 {{5, 1}, {4, 5}};
    vector<vector<int> > grid0 {{1, 2, 3}, {4, 5, 1}};
    vector<vector<int> > grid2 {{5, 1, 7}, {4, 8, 5}};
    vector<vector<int> > grid3 {{1, 9, 9}, {9, 9, 9}, {9, 9, 9}};
    vector<vector<int> > grid4 {{10, 7, 3}, {12, 11, 9}, {1, 2, 8}};
    vector<vector<int> > grid5 {{20, 20, 3}, {20, 3, 20}, {3, 20, 20}};

    cout << "Max score should be 4: " << maxScore(grid1) << "\n";
    cout << "Max score should be 4: " << maxScore(grid0) << "\n";
    cout << "Max score should be 4: " << maxScore(grid2) << "\n";
    cout << "Max score should be 9: " << maxScore(grid3) << "\n";
    cout << "Max score should be 9: " << maxScore(grid4) << "\n";
    cout << "Max score should be 3: " << maxScore(grid5) << "\n";
}


Java:

public class MaxMinScore {
    public static int maxMinScore(int[][] matrix) {
        int rows = matrix.length;
        int cols = matrix[0].length;
        int[][] dp = new int[rows][cols];
        dp[0][0] = Integer.MAX_VALUE;
        for (int i = 1; i < rows; i++) {
            dp[i][0] = Math.min(dp[i - 1][0], matrix[i][0]);
        }
        for (int i = 1; i < cols; i++) {
            dp[0][i] = Math.min(dp[0][i - 1], matrix[0][i]);
        }

        for (int i = 1; i < rows; i++) {
            for (int j = 1; j < cols; j++) {
                if (i == rows - 1 && j == cols - 1) {
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
                } else {
                    dp[i][j] = Math.max(Math.min(matrix[i][j], dp[i - 1][j]),
                            Math.min(matrix[i][j], dp[i][j - 1]));
                }
            }
        }
        return dp[rows - 1][cols - 1];
    }

    public static void main(String[] args) {
        int[][] matrix1 = {{5, 1}, {4, 5}};
        int[][] matrix2 = {{1, 2, 3}, {4, 5, 1}};
        int[][] matrix3 = {{5, 1, 7}, {4, 8, 5}};
        int[][] matrix4 = {{1, 9, 9}, {9, 9, 9}, {9, 9, 9}};
        int[][] matrix5 = {{10, 7, 3}, {12, 11, 9}, {1, 2, 8}};
        int[][] matrix6 = {{20, 20, 3}, {20, 3, 20}, {3, 20, 20}};

        System.out.println("should be 4: " + maxMinScore(matrix1));
        System.out.println("should be 4: " + maxMinScore(matrix2));
        System.out.println("should be 4: " + maxMinScore(matrix3));
        System.out.println("should be 9: " + maxMinScore(matrix4));
        System.out.println("should be 9: " + maxMinScore(matrix5));
        System.out.println("should be 3: " + maxMinScore(matrix6));
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值