Topic Requirements
Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules. The Sudoku board could be partially filled, where empty cells are filled with the character '.'. Note: A valid Sudoku board (partially filled) is not necessarily solvable. Only the filled cells need to be validated.
A Sudoku legal standard is as follows
Each row and column must contain every number between 1 and 9 (including 1 and 9)
Each small square matrix must contain every number between 1 and 9 (including 1 and 9).
So the general idea is to traverse Sudoku to determine whether the numbers in rows, columns and every small square are legitimate.
Sudoku as shown in the figure is a legal Sudoku.
Idea 1: Use StringBuilder API
Assuming that we hold all the rows and values of the squares that we have traversed, we only need to determine whether the current values are duplicated in our own rows, columns and squares. If repetition is not lawful, otherwise it is extremely lawful.
Here we use StringBuilder arrays instead of Map s as worthy data structures for storing rows and columns and small squares. We just need to use the StringBuilder API to determine if the current value is duplicated.
Note: If strings are more likely to be changed after new construction, it is recommended not to use String but String Builder, which can significantly improve efficiency.
The code is as follows
public boolean isValidSudoku(char[][] board) { //Nine StringBuilder s represent nine small squares StringBuilder[] squares = new StringBuilder[]{new StringBuilder(""),new StringBuilder(""),new StringBuilder(""),new StringBuilder(""),new StringBuilder(""),new StringBuilder(""),new StringBuilder(""),new StringBuilder(""),new StringBuilder("")}; //The 9 column StringBuilder[] columns = new StringBuilder[]{new StringBuilder(""),new StringBuilder(""),new StringBuilder(""),new StringBuilder(""),new StringBuilder(""),new StringBuilder(""),new StringBuilder(""),new StringBuilder(""),new StringBuilder("")}; //Current line StringBuilder line; for(int i = 0 ; i<board.length ; i++){ line = new StringBuilder(); for(int j = 0 ; j<board[i].length ; j++){ if(board[i][j] == '.'){ continue; } String currentChar = board[i][j]+""; if(line.indexOf(currentChar) != -1){ return false; } if(columns[j].indexOf(currentChar) != -1){ return false; } //Calculate the square of the current small square int squareNum = (i/3)*3 + (j/3); if(squares[squareNum].indexOf(currentChar) != -1){ return false; } line.append(currentChar); columns[j].append(currentChar); squares[squareNum].append(currentChar); } } return true; }
Idea 2: Use Subscripts
The idea of the previous method is quite intuitive. I store all the small squares of rows and columns and determine whether the current value is repeated. However, it's obvious that we don't need to keep an eye on all rows and columns, so when we focus on one row or column, we don't need to store other columns or small square values. So instead, we use the subscripts of double loops to represent rows, columns and small squares, reducing unnecessary data storage. Each inner loop represents a traversal of a row or a column or a small square. The outer loop represents the traversal of the next row, the next column and the next small square.
The code is as follows:
public boolean isValidSudoku(char[][] board) { for(int i = 0; i<9; i++){ HashSet<Character> rows = new HashSet<Character>(); HashSet<Character> columns = new HashSet<Character>(); HashSet<Character> cube = new HashSet<Character>(); for (int j = 0; j < 9;j++){ if(board[i][j]!='.' && !rows.add(board[i][j])) return false; if(board[j][i]!='.' && !columns.add(board[j][i])) return false; int RowIndex = 3*(i/3); int ColIndex = 3*(i%3); if(board[RowIndex + j/3][ColIndex + j%3]!='.' && !cube.add(board[RowIndex + j/3][ColIndex + j%3])) return false; } } return true; }