問題:Determine if a Sudoku is valid, according to: Here are three rules: 數組
Each row must have the numbers 1-9 occuring just once.spa |
|
![]() |
|
Each column must have the numbers 1-9 occuring just once.code |
![]() |
And the numbers 1-9 must occur just once in each of the 9 sub-boxes of the grid.three ![]() |
The Sudoku board could be partially filled, where empty cells are filled with the character '.'
.數學
A partially filled sudoku which is valid.it
Note:
A valid Sudoku board (partially filled) is not necessarily solvable. Only the filled cells need to be validated.io
解決:table
① 本題是驗證一個數獨(不必定是完整的,空白的元素用"."來代替)是不是正確的。class
九宮格的規則爲:date
由於只須要判斷已經填入的數字是否合法,那麼須要判斷每行每列以及每一個9宮格的數字是否有重複,很天然的聯想到HashSet,由於每一個Set裏面的元素是不能相同的。順着這個思路,那麼咱們爲行、列及九宮格各設置9個Hashset元素的數組,每次進行判斷便可。
class Solution { //34ms
public boolean isValidSudoku(char[][] board) {
HashSet[] row = new HashSet[9];
HashSet[] col = new HashSet[9];
HashSet[] cell = new HashSet[9];
for (int i = 0;i < 9 ;i ++ ) {
row[i] = new HashSet<Character>();
col[i] = new HashSet<Character>();
cell[i] = new HashSet<Character>();
}
for (int i = 0;i < 9 ;i ++ ) {
for (int j = 0;j < 9 ;j ++ ) {
if(board[i][j] != '.'){
if(row[i].contains(board[i][j]) ||
col[j].contains(board[i][j]) ||
cell[3 * (i / 3) + j / 3].contains(board[i][j]))//不能使用add方法判斷
return false;
else{
row[i].add(board[i][j]);
col[j].add(board[i][j]);
cell[3 * (i / 3) + j / 3].add(board[i][j]);
}
}
}
}
return true;
}
}
② 更詳細一點的解法。
本題難點在於表示第i個九宮格每一個格點的座標。
觀察行號規律:
第0個九宮格:000111222; 第1個九宮格:000111222; 第2個九宮格:000111222;
第3個九宮格:333444555; 第4個九宮格:333444555; 第5個九宮格:333444555;
第6個九宮格:666777888; 第7個九宮格:666777888; 第8個九宮格:666777888;
可見對於每三個九宮格行號增3;對於單個九宮格,每三個格點行號增1。
所以第i個九宮格的第j個格點的行號可表示爲i / 3 * 3 + j / 3
觀察列號規律:
第0個九宮格:012012012; 第1個九宮格:345345345; 第2個九宮格:678678678;
第3個九宮格:012012012; 第4個九宮格:345345345; 第5個九宮格:678678678;
第6個九宮格:012012012; 第7個九宮格:345345345; 第8個九宮格:678678678;
可見對於下個九宮格列號增3,循環週期爲3;對於單個九宮格,每一個格點行號增1,週期也爲3。
週期的數學表示就是取模運算mod。
所以第i個九宮格的第j個格點的列號可表示爲i % 3 * 3 + j % 3
public class Solution{//29ms
public boolean isValidSudoku(char[][] board) {
HashSet<Character> set = new HashSet<Character>();
// 驗證每行
for (int i = 0; i < 9; i ++) {
for (int j = 0; j < 9; j ++) {
if (board[i][j] == '.')
continue;
if (! set.add(board[i][j]))
return false;
}
set.clear();
}
// 驗證每列
for (int j = 0; j < 9; j ++) {
for (int i = 0; i < 9; i ++) {
if (board[i][j] == '.')
continue;
if (! set.add(board[i][j]))
return false;
}
set.clear();
}
// 驗證每一個子九宮格
for (int k = 0; k < 9; k ++) {
for (int i = k / 3 * 3; i < k / 3 * 3 + 3; i ++) {
for (int j = (k % 3) * 3; j < (k % 3) * 3 + 3; j ++) {
if (board[i][j] == '.')
continue;
if (! set.add(board[i][j]))
return false;
}
}
set.clear();
}
return true;
}
}
③ 進化版。。。。。
public class Solution {//28ms public boolean isValidSudoku(char[][] board) { int[] row = new int[9]; int[] col = new int[9]; int[] region = new int[9]; for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { if (board[i][j] != '.') { int mask = 1 << board[i][j] - '1'; int k = (i / 3) * 3 + j / 3; if ((row[i] & mask) > 0 || (col[j] & mask) > 0 || (region[k] & mask) > 0) { return false; } else { row[i] |= mask; col[j] |= mask; region[k] |= mask; } } } } return true; } }