算法总结-矩阵(正在更新)

参考:https://mp.weixin.qq.com/s/I1lu8cziVhjOrCwgRea-gQ

简述

矩阵类题目常常把思考的维度从一维扩展到二维,需要考虑的边界条件也相应增多,以矩阵为背景的题目大多有动态规划类型、记忆搜索类型、深度优先搜索类型等等。接下来将实例进行讲解:

题目1:格子走法总数

题目描述:有xy大小的格子,只能从左往右、从上往下走,问从左上到右下有多少种走法
示例:
一个2
3的矩阵,
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];
    }
}

猜你喜欢

转载自blog.csdn.net/qq_37886086/article/details/90168314