Leetcode热题100中的:矩阵专题

矩阵框架

1.坐标变换型

  • 旋转,翻转,变换

2.按圈遍历型

  • 螺旋,顺时针,按层遍历

3.原地标记型

  • 整行整列修改,传播,标记

4.单调矩阵搜索型

  • 行递增,列递增,搜索

5.矩阵DP / 面积型

73.矩阵置零(原地标记型)

关键信息一句话总结:

将第一行和第一列作为标志数组,标记置零,最后自己也变成0

  • 方法1:利用标记数组
java 复制代码
class Solution {
    public void setZeroes(int[][] matrix) {
        // 双数组标记法
        int n = matrix.length;
        int m = matrix[0].length;
        boolean[] row = new boolean[n];
        boolean[] col = new boolean[m];
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < m; j++) {
                if(matrix[i][j] == 0) {
                    row[i] = true;
                    col[j] = true;
                }
            }
        }
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < m; j++) {
                // 只要第j列或者第i行需要清零 该位置才是0 
                if(row[i] || col[j]) {
                    matrix[i][j] = 0;
                }
            }
        }
    }
}
  • 方法2:优化第一行和第一列作为标志数组
java 复制代码
class Solution {
    public void setZeroes(int[][] matrix) {
        // 优化思路:将标志数组放进第一行和第一列
        int n = matrix.length;
        int m = matrix[0].length;
        boolean firstRow = false;
        boolean firstCol = false;
        // 1.先检测第一行是否有0 我们后面再处理
        for(int j = 0; j < m; j++) {
            if(matrix[0][j] == 0) {
                firstRow = true;
                break;
            }
        }
        // 2.再检测第一列是否有0 我们后面再处理
        for(int i = 0; i < n; i++) {
            if(matrix[i][0] == 0) {
                firstCol = true;
                break;
            }
        }
        // 3.开始标记
        for(int i = 1; i < n; i++) {
            for(int j = 1; j < m; j++) {
                if(matrix[i][j] == 0) {
                    matrix[0][j] = 0;
                    matrix[i][0] = 0; 
                }
            }
        }
        // 4.开始填0
        for(int i = 1; i < n; i++) {
            for(int j = 1; j < m; j++) {
                if(matrix[0][j] == 0 || matrix[i][0] == 0) {
                    matrix[i][j] = 0;
                }
            }
        }
        // 5.第一行和第一列清零
        if(firstRow) {
            for(int j = 0; j < m; j++) {
                matrix[0][j] = 0;
            }
        }
        if(firstCol) {
            for(int i = 0; i < n; i++) {
                matrix[i][0] = 0;
            }
        }
    }
}
  • 反思:我没有想到矩阵的第一列和第一行能够作为标志数组进行优化

54.螺旋矩阵(按圈遍历型)

关键信息一句话总结:

利用四边界,将边界进行收缩

  • 方法1:利用%进行方向判断,用isVisited标志数组判断访问
java 复制代码
class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> result = new ArrayList<>();
        int n = matrix.length;
        int m = matrix[0].length;
        boolean[][] isVisited = new boolean[n][m];
        // dx: 右0 下+1 左0 上-1
        int[] dx = new int[]{0, 1, 0, -1};
        // dy: 右+1 下0 左-1 上0
        int[] dy = new int[]{1, 0, -1, 0}; 
        int x = 0;
        int y = 0;
        // 当前方向 0表示右
        int dir = 0;
        for(int i = 0; i < n * m; i++) {
            result.add(matrix[x][y]);
            isVisited[x][y] = true;
            int nx = x + dx[dir];
            int ny = y + dy[dir];
            if(nx < 0 || nx >= n || ny < 0 || ny >= m || isVisited[nx][ny]) {
                // 转换方向
                dir = (dir + 1) % 4;
            }
            // 移动坐标
            x += dx[dir];
            y += dy[dir];
        }
        return result;
    }
}
  • 方法2:优化思路:利用边界收缩来替换方向判断
java 复制代码
class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
        // 四边界法: 优化思路:判断下一个元素是否访问过用 + 方向如何判断
        // 用四个边界来进行按要求访问 通过收缩边界来进行访问元素
        List<Integer> result = new ArrayList<>();
        int top = 0;
        int bottom = matrix.length - 1;
        int left = 0;
        int right = matrix[0].length - 1;
        while(top <= bottom && left <= right) {
            // ->right
            for(int j = left; j <= right; j++) {
                result.add(matrix[top][j]);
            }
            top++;
            // ->down
            for(int i = top; i <= bottom; i++) {
                result.add(matrix[i][right]);
            }
            right--;
            // ->left
            if(top <= bottom) {
                for(int j = right; j >= left; j--) {
                    result.add(matrix[bottom][j]);
                }
                bottom--;
            }
            // ->up
            if(left <= right) {
                for(int i = bottom; i >= top; i--) {
                    result.add(matrix[i][left]);
                }
                left++;
            }
        }
        return result;
    }
}
  • 反思:我没有想到四边界收缩法,可以利用边界收缩来对应优化方向判断和访问记录

48.旋转图像(坐标变换型)

关键信息一句话总结:

转置 + 每一行逆序 模拟 顺时针90°旋转

java 复制代码
class Solution {
    public void rotate(int[][] matrix) {
        int n = matrix.length;
        // (i , j) → (j , n-1-i)
        // 1.对角线转置
        for(int i = 0; i < n; i++) {
            for(int j = i + 1; j < n; j++) {
                int temp = matrix[i][j];
                matrix[i][j] = matrix[j][i];
                matrix[j][i] = temp;
            }
        }
        // 2.每一行倒置
        for(int i = 0; i < n; i++) {
            // 3.双指针倒置
            int left = 0;
            int right = n - 1;
            while(left < right) {
                int temp = matrix[i][left];
                matrix[i][left] = matrix[i][right];
                matrix[i][right] = temp; 
                left++;
                right--;
            }
        }
    }
}
  • 反思:我没有观察出来坐标的变化

240.搜索二维矩阵II(单调矩阵搜索型)

关键信息一句话总结:

右上角开始搜索,右上角的特征是左小下大,收缩搜索范围

java 复制代码
class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        // 从右上角开始 因为左边都小 下边都大
        int n = matrix.length;
        int m = matrix[0].length;
        int x = 0;
        int y = m - 1;
        while(x < n && y >= 0) {
            if(target == matrix[x][y]) {
                return true;
            }
            if(matrix[x][y] > target) {
                y--;
            } else {
                x++;
            }
        }
        return false;
    }
}
  • 反思:我没有观察出来右上角的特征
相关推荐
Tisfy2 小时前
LeetCode 3296.移山所需的最少秒数:优先队列
算法·leetcode·题解·优先队列·模拟
㓗冽2 小时前
龟兔赛跑预测-进阶题6
算法
云泽8082 小时前
蓝桥杯算法精讲:贪心算法的简单应用与题解
算法·贪心算法·蓝桥杯
程序员夏末2 小时前
【LeetCode | 第四篇】算法笔记
笔记·算法·leetcode
DeepModel2 小时前
【概率分布】多项分布详解
算法·概率论
_日拱一卒2 小时前
LeetCode(力扣):只出现一次的数字
java·数据结构·算法
bulingg2 小时前
LR逻辑回归详解
算法·机器学习·逻辑回归
七七肆十九2 小时前
PTA 习题4-7 最大公约数和最小公倍数
数据结构·算法
NGC_66112 小时前
八大排序对比及实现
数据结构·算法·排序算法