参考:https://mp.weixin.qq.com/s/I1lu8cziVhjOrCwgRea-gQ
简述
矩阵类题目常常把思考的维度从一维扩展到二维,需要考虑的边界条件也相应增多,以矩阵为背景的题目大多有动态规划类型、记忆搜索类型、深度优先搜索类型等等。接下来将实例进行讲解:
题目1:格子走法总数
题目描述:有xy大小的格子,只能从左往右、从上往下走,问从左上到右下有多少种走法
示例:
一个23的矩阵,
1 2 3
4 5 6
从1出发走到6,则可能的走法为:1 2 3 6, 1 2 5 6, 1 4 5 6共有三种。
解决思路:从最后一个格子进行倒推,需要找到关系方程:res[i][j] = res[i-1][j] + res[i][j-1],然后可以用递归或者非递归的方法进行求解。
方法1:递归求解
(注:下面代码可左右滑动查看)
public static int numPath(int x, int y) {
if(x==1||y==1) return 1;
return numPath2(x-1, y) + numPath2(x, y-1);
}
方法2:非递归求解(注:下面代码可左右滑动查看)
public static int numPath(int x, int y) {
if(x == 1 || y == 1){
return 1;
}
int[][] res = new int[x][y];
for(int i = 0; i < x; i++){
res[i][0] = 1;
}
for(int i = 0; i < y; i++){
res[0][i] = 1;
}
for(int i = 1; i < x; i++) {
for(int j = 1; j < y; j++) {
res[i][j] = res[i-1][j] + res[i][j-1];
}
}
return res[x-1][y-1];
}
题目2:矩阵中的最长递增路径
题目描述:给定一个整数矩阵,找出最长递增路径的长度。对于每个单元格,你可以往上,下,左,右四个方向移动。 你不能在对角线方向上移动或移动到边界外(即不允许环绕)。
示例:
输入: nums =
[
[9,9,4],
[6,6,8],
[2,1,1]
]
输出: 4
解释: 最长递增路径为 [1, 2, 6, 9]。
解决思路:深度优先搜索与动态规划相结合
(1)深度优先搜索需要注意边界条件,若下一个值小于当前值,则返回0;否则继续递归判断;
(2)动态规划需要记录历史数据,建立一个二维数组int[][] dp,记录历史数据,防止重复计算; 注:下面代码可左右滑动查看
class Solution {
public int longestIncreasingPath(int[][] matrix) {
if (matrix.length == 0) {
return 0;
}
//建立二维数组记录历史数据
int[][] dp = new int[matrix.length][matrix[0].length];
//最长递增路径的长度
int maxLen = 0;
//双重循环遍历所有的点,获得最大值
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
maxLen = Math.max(maxLen, dfs(matrix, dp, i, j, Integer.MIN_VALUE));
}
}
return maxLen;
}
private int dfs(int[][] matrix, int[][] dp, int i, int j, int temp) {
// 边界判断
if (i < 0 || j < 0 || i > matrix.length - 1 || j > matrix[i].length - 1) {
return 0;
}
// 是否递增判断
if (matrix[i][j] <= temp) {
return 0;
}
// 如果该点已经判断过,则直接返回结果
if (dp[i][j] != 0) {
return dp[i][j];
}
int left = dfs(matrix, dp, i - 1, j, matrix[i][j]);
int right = dfs(matrix, dp, i + 1, j, matrix[i][j]);
int up = dfs(matrix, dp, i, j - 1, matrix[i][j]);
int down = dfs(matrix, dp, i, j + 1, matrix[i][j]);
dp[i][j] = 1 + Math.max(Math.max(left, right), Math.max(up, down));
return dp[i][j];
}
}