一 题目
Determine if a 9x9 Sudoku board is valid. Only the filled cells need to be validated according to the following rules:
- Each row must contain the digits
1-9
without repetition. - Each column must contain the digits
1-9
without repetition. - Each of the 9
3x3
sub-boxes of the grid must contain the digits1-9
without repetition.
A partially filled sudoku which is valid.
The Sudoku board could be partially filled, where empty cells are filled with the character '.'
.
Example 1:
Input: [ ["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: [ ["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 Explanation: Same as Example 1, except with the 5 in the top left corner being modified to 8. Since there are two 8's in the top left 3x3 sub-box, it is invalid.
Note:
- A Sudoku board (partially filled) could be valid but is not necessarily solvable.
- Only the filled cells need to be validated according to the mentioned rules.
- The given board contain only digits
1-9
and the character'.'
. - The given board size is always
9x9
.
二 分析
本题 medium 级别。求一个9*9格子的数独是否有效。
有效的规则:
行里面的数字不重复。
列里面的数字不重复。
以3*3 小格子里面的数字不重复。
数独里面的数字不全填满,用“.”表示空格。复合规则的数独不一定有解。
没啥技巧,就是按照规则去校验。最简单就是使用hashset. (利用add方法,当添加成功(即set中不含有该元素)返回true)
改进一下,就是使用额外的boolean二维数组 保存是否出现过。默认为false,每次遍历完设为true。其中通过对应下标 board[i][j]-'0'-1 是否为true判断此数字是否存在过. -'0'是 char转换为数字,-1 是索引从0开始。所以有的文章直接使用了-‘1’表示。
我觉得难点在于3*3 小格子判断是否重复,大神可能不做过多解释直接贴代码了。还是画图有助于理解,我开始还是使用了步进为3的方式去处理,看了别人的文章也没一下明白怎么回事,缺乏抽象逻辑思维。
就是坐标转换,把9*9的格子分为0-8 的9个小区域。根据(i,j) 转换为对应的小格子编码。如图所示。
3*(i/3)+j/3;
代码如下:
char[][] 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'}
};
System.out.println( isValidSudoku(board) );
}
public static boolean isValidSudoku(char[][] board) {
if(board == null ){
return false;
}
boolean[][] rowused = new boolean[9][9];
boolean[][] colused = new boolean[9][9];
boolean[][] small = new boolean[9][9];
for(int i=0;i<9;i++ ){
for(int j=0;j<9;j++ ){
if (board[i][j] == '.'){
continue;
}
int idx = board[i][j] - '0' - 1;
//check行
if (rowused[i][idx]==true){
return false;
}
rowused[i][idx]=true;
//check列
if (colused[j][idx]==true){
return false;
}
colused[j][idx] =true;
//check 9个格子
int area = (i/3)*3+(j/3);
if( small[area][idx]==true ){
return false;
}
small[area][idx ]=true ;
}
}
return true;
}
Runtime: 2 ms, faster than 89.01% of Java online submissions for Valid Sudoku.
Memory Usage: 43.2 MB, less than 95.65% of Java online submissions forValid Sudoku.
时间复杂度:O(N^2).