LeetCode之矩阵

36. 有效的数独

class Solution {
    // 方法 isValidSudoku 接收一个字符二维数组 board,表示数独棋盘,返回是否有效
    public boolean isValidSudoku(char[][] board) {
        // 创建三个二维数组来记录每一行、列和子框中数字的出现次数
        int[][] rows = new int[9][9];      // 行记录
        int[][] columns = new int[9][9];   // 列记录
        int[][][] subboxes = new int[3][3][9]; // 子框记录

        // 遍历整个棋盘
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                char c = board[i][j]; // 当前单元格的字符
                // 如果单元格不是空格(即不是 '.')
                if (c != '.') {
                    // 计算当前数字的索引(1-9 映射到 0-8) 如果重复相同的数映射到同一个位置会不断+1,如果重复就会大于1
                    int index = c - '0' - 1; 
                    // 在行、列和子框中更新当前数字的出现次数
                    rows[i][index]++;        // 增加行的计数
                    columns[j][index]++;     // 增加列的计数
                    subboxes[i / 3][j / 3][index]++; // 增加子框的计数

                    // 如果某个位置的计数超过 1,说明出现重复,返回 false
                    if (rows[i][index] > 1 || columns[j][index] > 1 || subboxes[i / 3][j / 3][index] > 1) {
                        return false; // 数独无效
                    }
                }
            }
        }
        // 如果循环结束,说明没有发现重复,返回 true
        return true; // 数独有效
    }
}

54. 螺旋矩阵

class Solution {

    // // 方法 spiralOrder 接收一个二维整数数组 matrix,返回矩阵的螺旋顺序遍历结果
    public List<Integer> spiralOrder(int[][] matrix) {
        // 获取矩阵的行数
        int m = matrix.length;
        // 获取矩阵的列数
        int n = matrix[0].length;
        // 定义四个边界
        // 上边界
        int up = 0;
        // 左边界
        int left = 0;
        // 右边界
        int right = n - 1;
        // 下边界
        int down = m - 1;

        // 存储结果的列表
        List<Integer> result =  new ArrayList<>();

        // 使用循环遍历,直到所有元素都被访问
        while(true) {
            // 从左到右遍历上边界
            for (int i = left; i <= right; i++) {
                // 添加当前元素到结果列表中
                result.add(matrix[up][i]);
            }
            // 更新上边界,检查是否已超出下边界
            if (++up > down) {
                // 如果上边界超过下边界,结束循环
                break;
            }

            // 从上到下遍历右边界
            for (int i = up; i <= down; i++) {
                result.add(matrix[i][right]); // 添加当前元素到结果列表中
            }
            // 更新右边界,检查是否已超出左边界
            if (--right < left) {
                break; // 如果右边界超过左边界,结束循环
            }

            // 从右到左遍历下边界
            for (int i = right; i >= left; i--) {
                result.add(matrix[down][i]); // 添加当前元素到结果列表中
            }
            // 更新下边界,检查是否已超出上边界
            if (--down < up) {
                break; // 如果下边界超过上边界,结束循环
            }

            // 从下到上遍历左边界
            for (int i = down; i >= up; i--) {
                result.add(matrix[i][left]); // 添加当前元素到结果列表中
            }
            // 更新左边界,检查是否已超出右边界
            if (++left > right) {
                break; // 如果左边界超过右边界,结束循环
            }
        }
        
        // 返回螺旋顺序遍历的结果
        return result;
    }

}

48. 旋转图像

class Solution {

    // 方法 rotate 接收一个二维整数数组 matrix,表示要旋转的矩阵
    public void rotate(int[][] matrix) {
        // 获取矩阵的行数 m
        int m = matrix.length;
        // 获取矩阵的列数 n
        int n = matrix[0].length;

        // 创建一个临时矩阵,用于存储原矩阵的值
        int[][] temp = new int[m][];
        for (int i = 0; i < m; i++) {
            // 深拷贝原矩阵的每一行,以防旋转时修改原矩阵的值
            temp[i] = matrix[i].clone(); // 使用 clone() 方法进行深拷贝
        }

        // 遍历临时矩阵,将值重新赋值到原矩阵中的适当位置,完成顺时针旋转
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                // 根据旋转公式,把 temp[i][j] 放到 matrix[j][n - 1 - i]
                matrix[j][n - 1 - i] = temp[i][j];
            }
        }
    }
    
}

73. 矩阵置零

class Solution {
    // 方法 setZeroes 接收一个二维整数数组 matrix,表示要处理的矩阵
    public void setZeroes(int[][] matrix) {
        int m = matrix.length; // 获取矩阵的行数
        int n = matrix[0].length; // 获取矩阵的列数
        
        // 创建两个标记数组,用于记录需要置零的行和列
        boolean[] row = new boolean[m]; // 行标记位
        boolean[] col = new boolean[n]; // 列标记位

        // 第一次遍历整个矩阵,查找值为 0 的元素
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (matrix[i][j] == 0) { // 如果当前元素为 0
                    row[i] = true; // 将对应的行标记为 true
                    col[j] = true; // 将对应的列标记为 true
                }
            }
        }

        // 第二次遍历,根据标记修改矩阵中的元素
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                // 如果该行或该列需要置为 0,则将当前元素设置为 0
                if (row[i] || col[j]) {
                    matrix[i][j] = 0; // 设置当前元素为 0
                }
            }
        }
    }
}

289. 生命游戏

class Solution {
    // 方法 gameOfLife 接收一个二维整数数组 board,表示细胞的当前状态
    public void gameOfLife(int[][] board) {
        // 创建一个数组来表示邻居的位置变化,邻居可以在横向、纵向和对角线
        int[] neighbors = {0, 1, -1}; 
        int rows = board.length; // 获取行数
        int cols = board[0].length; // 获取列数
        
        // 创建一个复制数组 copyBoard,用于存储当前状态
        int[][] copyBoard = new int[rows][cols];
        
        // 从原数组复制一份到 copyBoard 中
        for (int row = 0; row < rows; row++) {
            for (int col = 0; col < cols; col++) {
                copyBoard[row][col] = board[row][col]; // 深拷贝细胞状态
            }
        }

        // 遍历面板中的每一个细胞
        for (int row = 0; row < rows; row++) {
            for (int col = 0; col < cols; col++) {
                // 统计当前细胞八个相邻细胞中的活细胞数量
                int liveNeighbors = 0;

                // 检查当前细胞的所有邻居
                for (int i = 0; i < 3; i++) { // 遍历邻居的行偏移
                    for (int j = 0; j < 3; j++) { // 遍历邻居的列偏移
                        // 排除当前细胞自身
                        if (!(neighbors[i] == 0 && neighbors[j] == 0)) {
                            int r = (row + neighbors[i]); // 计算邻居的行坐标
                            int c = (col + neighbors[j]); // 计算邻居的列坐标

                            // 检查邻居是否在矩阵内,并且是活细胞
                            if ((r < rows && r >= 0) && (c < cols && c >= 0) && (copyBoard[r][c] == 1)) {
                                liveNeighbors += 1; // 统计活细胞数量
                            }
                        }
                    }
                }

                // 应用生命游戏规则:
                // 规则 1 或 规则 3:活细胞与少于 2 个或多于 3 个活邻居则死亡
                if ((copyBoard[row][col] == 1) && (liveNeighbors < 2 || liveNeighbors > 3)) {
                    board[row][col] = 0; // 死亡
                }
                // 规则 4:死细胞有正好 3 个活邻居则复活
                if (copyBoard[row][col] == 0 && liveNeighbors == 3) {
                    board[row][col] = 1; // 复活
                }
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值