Valid Sudoku

Title Description

Difficulty: Medium

Please judge if a 9x9 number is valid. Just verify that the number you have filled in is valid according to the following rules.

Numbers 1-9 can only appear once per line.
Numbers 1-9 can only appear once in each column.
Numbers 1-9 can only occur once in each 3x3 uterus separated by a thick solid line. (See example diagram)
Sudoku is filled with numbers, which are indicated by'.'.

Be careful:

A valid Sudoku (partially filled) is not necessarily solvable.
Simply verify that the numbers you have filled in are valid according to the rules above.

Example 1:

Input: board = 
[["5","3",".",".","7",".",".",".","."]
,["6",".",".","1","9","5",".",".","."]
,[".","9","8",".",".",".",".","6","."]
,["8",".",".",".","6",".",".",".","3"]
,["4",".",".","8",".","3",".",".","1"]
,["7",".",".",".","2",".",".",".","6"]
,[".","6",".",".",".",".","2","8","."]
,[".",".",".","4","1","9",".",".","5"]
,[".",".",".",".","8",".",".","7","9"]]
Output: true

Example 2:

Input: board = 
[["8","3",".",".","7",".",".",".","."]
,["6",".",".","1","9","5",".",".","."]
,[".","9","8",".",".",".",".","6","."]
,["8",".",".",".","6",".",".",".","3"]
,["4",".",".","8",".","3",".",".","1"]
,["7",".",".",".","2",".",".",".","6"]
,[".","6",".",".",".",".","2","8","."]
,[".",".",".","4","1","9",".",".","5"]
,[".",".",".",".","8",".",".","7","9"]]
Output: false

Interpretation: Except that the first number in the first row changes from 5 to 8, all the numbers in the space are the same as in Example 1. However, since there are two 8 in the 3x3 uterus in the upper left corner, this number is invalid.

Tips:

board.length == 9
board[i].length == 9
board[i][j] Is a number or '.'

Analysis

When I see this, I think of HashSet duplication; I iterate through it by row, column, and square, and then use HashSetCheck, the traversal of rows and columns is very good, that is, the rules of traversal of squares are difficult for me and I barely thought about them for half a day; the code is written out, but the code is so ugly, especially pure violence, that the entire two-dimensional array is traversed three times, interspersed with various nested for loops;
Tested the execution example and found that it could run, but did not submit, the code was long and smelly, I was shy to submit, and finally I flipped through the official solution.
When you see the official solution, you see the normal solution. The idea is to use a two-dimensional array instead of HashMap to check the weight, and to traverse it only once.

We define two two two-dimensional arrays, int[][] rows = new int[9][9];Int[][] columns = new int[9][9];Rows are used to determine the number of occurrences of each element in each row, and columns is used to determine the number of occurrences of each element in each column.
For example, line 0 has four elements 1, 3, 5, 3 so we can understand the code rows [0][1]+;Rows[0][3] += 2;Rows[0][5]++;That way, we know that there are duplicate elements in line 0, because rows [0][3] > 1;

Then there are 3x3 small squares. The large two-dimensional array is cut into nine small squares. Each small square is treated as a whole, so you can access the small squares. boxes[0][0] is the small square in the first row, column 1, and boxes[2][2] is the small square in the third row, column 3, and so on.
There are nine elements in each small square, so the definition of a small square is int[][][] boxes = new int[3][3][9];
Repeated elements in small squares can be determined by boxes[i/3][j/3][index];
Since the element is limited to 1 <= x <= 9 in the final index determination, a -1 operation is required to compute the index, conforming to the array subscript;

Code:

 public boolean isValidSudoku(char[][] board) {
        int[][] rows = new int[9][9];      // 9 rows record the number of occurrences of each element in each row
        int[][] columns = new int[9][9];   // 9 columns record the number of occurrences of each element in each column
        int[][][] boxes = new int[3][3][9];  // Divide the whole square into nine small squares Nine elements within each small square [0][0] are the first square [0][1] are the second square and so on

        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++){
                char c = board[i][j];
                if(c != '.'){
                    int index = c - '0' - 1;  // Calculate the index for this element
                    rows[i][index]++;        // The index element in line i appears once
                    columns[j][index]++;     // The index element of column j appears once
                    boxes[i / 3][j / 3][index]++; // The index element of the corresponding square appears once
                    if(rows[i][index] > 1 || columns[j][index] >1 || boxes[i / 3][j / 3][index] > 1){  // There are elements that occur twice or more
                        return false;
                    }
                }

            }
        }
        return true;
    }

summary

This question uses arrays instead of hash tables. It only needs to traverse the array once, update the counts in the array during traversal, and determine if the conditions for a valid Sudoku are met. It's not easy to write, nor is it easy to think like this. Keep it up!



Years are long and the skin is weak; to give up enthusiasm, decadence leads to soul

Tags: Java leetcode

Posted on Sat, 18 Sep 2021 13:26:15 -0400 by MVSS