day13-36/73/+六道复习题

26 阅读3分钟

第一题-有效的数独

题目

请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。

  1. 数字 1-9 在每一行只能出现一次。
  2. 数字 1-9 在每一列只能出现一次。
  3. 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)

 

注意:

  • 一个有效的数独(部分已被填充)不一定是可解的。
  • 只需要根据以上规则,验证已经填入的数字是否有效即可。
  • 空白格用 '.' 表示

image.png

思路

这一题,我只能想出来暴力破解啊,只能一点点遍历到每一个数进行判断,我看到官方的题解定义的是三个二维数组,我感觉只要维护三个一维数组就可以了分别是3*3,遇到不符合的,直接返回false

双层for循环遍历到每一个元素,i,j互换就是能行和列都能有了,比较难思考的是关于3*3宫格的处理,我这边想的是取一个到一个i,j的节点然后3*3遍历;

不过官方的代码确实简单;可以考虑根据官方代码看怎么进行简化一下;

代码

    public boolean isValidSudoku(char[][] board) {
        boolean res = true;
        endLoop:
            for(int i = 0; i < 9; i++) {
                int[] arrNumRow = new int[9];
                int[] arrNumClo = new int[9];
                for(int j = 0; j < 9; j++) {
                    if(board[i][j] != '.') {
                        int numRow = board[i][j] - '0';
                        arrNumRow[numRow -1]++;
                        if(arrNumRow[numRow -1] > 1) {
                            res = false;
                            break endLoop;
                        };
                    };
                    if(board[j][i] != '.') {
                        int numClo = board[j][i] - '0';
                        arrNumClo[numClo -1]++;
                        if(arrNumClo[numClo -1] > 1) {
                            res = false;
                            break endLoop;
                        };
                    };
                    if(((i+1)%3 == 0) && ((j+1) % 3 == 0)) {
                        int[] arrNumRan = new int[9];
                        for(int m = i - 2; m < i+1; m++) {
                            for(int n = j-2; n < j+1; n++) {
                                if(board[m][n] != '.') {
                                    int num = board[m][n] - '0';
                                    arrNumRan[num -1]++;
                                    if(arrNumRan[num -1] > 1) {
                                        res = false;
                                        break endLoop;
                                    };
                                };
                            };
                        };
                    };
                };
            };
        return res;
    }

第二题-矩阵置零

题目

给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法

image.png

思路

这个我最开始想的是,直接遍历置零,需要考虑的是,置完零后,i和j应该怎么取,但是!这个思路没有做出来,应该就是错的,看了官方题解:

使用标记变量,标记原本的矩阵第一行和第一列是否有0

然后从index为1开始遍历矩阵,某一个i,j位置为0,则把这个ij位置的首行和首列置为0

结束上述遍历,开始遍历首行和首列,把对应为0的每行每列置为0

根据标记变量,如果首行/首列为0,首行/首列置为0

代码

    public void setZeroes(int[][] matrix) {
        int i = 1, j = 1;
        boolean indexRow = false, indexClo = false;
        for(int m = 0; m < matrix.length; m++) {
            if(matrix[m][0] == 0) indexRow = true;
        };
        for(int m = 0; m < matrix[0].length; m++) {
            if(matrix[0][m] == 0) indexClo = true;
        };
        while(i < matrix.length && j < matrix[0].length) {
            if(matrix[i][j] == 0) {
                matrix[i][0] = matrix[0][j] = 0;
            }
            if(j == matrix[0].length -1) {
                i++;
                j = 1;
            }else {
                j++;
            };
        };
        i = 1;
        j = 1;
        while(i < matrix.length && j < matrix[0].length) {
            if(matrix[i][0] == 0 || matrix[0][j] == 0) {
                matrix[i][j] = 0;
            };
            if(j == matrix[0].length -1) {
                i++;
                j = 1;
            }else {
                j++;
            };
        };
        if(indexRow) {
            for(int m = 0; m < matrix.length; m++) {
                matrix[m][0] = 0;
            };
        };

        if(indexClo) {
            for(int m = 0; m < matrix[0].length; m++) {
                matrix[0][m] = 0;
            };
        };
    }