接下来我们深入一下,看几道矩阵类型的题目:
62. 不同路径
一个机器人位于一个 m x n
网格的左上角 (起始点在下图中标记为 “Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。
问总共有多少条不同的路径?
对于每一个i,j都是到到第i-1,j和i,j-1位置的和
所以有 d p [ i ] [ j ] = d p [ i − 1 ] [ j ] + d p [ i ] [ j − 1 ] dp[i][j] = dp[i-1][j] + dp[i][j-1] dp[i][j]=dp[i−1][j]+dp[i][j−1]
class Solution {
public:
int uniquePaths(int m, int n)
{
int dp[m][n];
// 对于边界,到达路径只有1种可能
for (int i = 0; i < m; i++) dp[i][0] = 1;
for (int i = 0; i < n; i++) dp[0][i] = 1;
for (int i = 1; i < m; i++)
{
for (int j = 1; j < n; j++)
{
dp[i][j] = dp[i-1][j] + dp[i][j-1];
}
}
int cc = dp[m-1][n-1];
return cc;
}
};
64. 最小路径和
给定一个包含非负整数的 *m* x *n*
网格 grid
,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
**说明:**每次只能向下或者向右移动一步。
该题目和上面的题目有异曲同工之妙
class Solution {
public:
int minPathSum(vector>& grid)
{
int n = grid.size(); int m = grid[0].size();
int dp[n][m]; dp[0][0] = grid[0][0];
for (int i = 1; i < n; i++) dp[i][0] = dp[i-1][0] + grid[i][0];
for (int i = 1; i < m; i++) dp[0][i] = dp[0][i-1] + grid[0][i];
for (int i = 1; i < n; i++)
{
for (int j = 1; j < m; j++)
{
dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid[i][j];
}
}
return dp[n-1][m-1];
}
};
63. 不同路径 II
一个机器人位于一个 m x n
网格的左上角 (起始点在下图中标记为 “Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish”)。
现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?
网格中的障碍物和空位置分别用 1
和 0
来表示。
该题目是62的进阶版,有障碍物的位置设置为不可达即可
class Solution {
public:
int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid)
{
int n = obstacleGrid.size();
int m = obstacleGrid[0].size();
int *f = new int[m];
memset(f, 0, m * 4);
f[0] = (obstacleGrid[0][0] == 0);
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
if (obstacleGrid[i][j] == 1)
{
f[j] = 0;
continue;
}
if (j -1 >=0 && obstacleGrid[i][j-1] == 0)
{
f[j]+=f[j-1];
}
}
}
int val = f[m-1];
delete [] f;
return val;
}
};
120. 三角形最小路径和
给定一个三角形 triangle
,找出自顶向下的最小路径和。
每一步只能移动到下一行中相邻的结点上。相邻的结点 在这里指的是 下标 与 上一层结点下标 相同或者等于 上一层结点下标 + 1 的两个结点。也就是说,如果正位于当前行的下标 i
,那么下一步可以移动到下一行的下标 i
或 i + 1
。
class Solution {
public:
int minimumTotal(vector<vector<int>>& triangle)
{
int n = triangle.size();
vector<vector<int>> f(n, vector<int>(n));
f[0][0] = triangle[0][0];
for (int i = 1; i < n; ++i) {
f[i][0] = f[i - 1][0] + triangle[i][0];
for (int j = 1; j < i; ++j) {
f[i][j] = min(f[i - 1][j - 1], f[i - 1][j]) + triangle[i][j];
}
f[i][i] = f[i - 1][i - 1] + triangle[i][i];
}
return *min_element(f[n - 1].begin(), f[n - 1].end());
}
};
931. 下降路径最小和
给你一个 n x n
的 方形 整数数组 matrix
,请你找出并返回通过 matrix
的下降路径 的 最小和 。
下降路径 可以从第一行中的任何元素开始,并从每一行中选择一个元素。在下一行选择的元素和当前行所选元素最多相隔一列(即位于正下方或者沿对角线向左或者向右的第一个元素)。具体来说,位置 (row, col)
的下一个元素应当是 (row + 1, col - 1)
、(row + 1, col)
或者 (row + 1, col + 1)
。
class Solution {
public:
int minFallingPathSum(vector<vector<int>>& matrix)
{
int n = matrix.size();
vector<vector<int>> dp(n, vector<int>(n));
// 初始化最初一行的dp
copy(matrix[0].begin(), matrix[0].end(), dp[0].begin());
// 推出之后的没一个下降
// dp[i][j]=matrix[i][j]+min(dp[i−1][j−1],dp[i−1][j],dp[i−1][j+1])
for (int i = 1; i < n; i++) {
for (int j = 0; j < n; j++) {
int mn = dp[i - 1][j];
if (j > 0) {
mn = min(mn, dp[i - 1][j - 1]);
}
if (j < n - 1) {
mn = min(mn, dp[i - 1][j + 1]);
}
dp[i][j] = mn + matrix[i][j];
}
}
return *min_element(dp[n - 1].begin(), dp[n - 1].end());
}
};
221. 最大正方形
在一个由 '0'
和 '1'
组成的二维矩阵内,找到只包含 '1'
的最大正方形,并返回其面积。
class Solution {
public:
int maximalSquare(vector<vector<char>>& matrix)
{
if (matrix.size() == 0 || matrix[0].size() == 0) return 0;
int maxSide = 0;
int rows = matrix.size(), columns = matrix[0].size();
vector<vector<int>> dp(rows, vector<int>(columns));
for (int i = 0; i < rows; ++i)
{
for (int j = 0; j < columns; j++)
{
if (matrix[i][j] == '1')
{
if (i == 0 || j == 0)
{
dp[i][j] = 1;
}
else
{
dp[i][j] = min(min(dp[i-1][j], dp[i][j-1]), dp[i-1][j-1]) + 1;
}
maxSide = max(maxSide, dp[i][j]);
}
}
}
int maxSquare = maxSide * maxSide;
return maxSquare;
}
};