判斷一個 9x9 的數獨是否有效。只需要根據以下規則,驗證已經填入的數字是否有效即可。
- 數字 1-9 在每一行只能出現一次。
- 數字 1-9 在每一列只能出現一次。
- 數字 1-9 在每一個以粗實線分隔的 3x3 宮內只能出現一次。
數獨部分空格內已填入了數字,空白格用 '.' 表示。
思路:
每一行必須是數字1~9且不重復
每一列必須是數字1~9且不重復
每一個小九宮格(互不交叉,總共九個小九宮格)必須是數字1~9且不重復
依次檢查每行,每列,每個子九宮格是否出現重復元素,如果出現返回false,否則返回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(每個小九宮格j都是從0~9遞增)
觀察列號規律:
第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(每個小九宮格j都是從0~9遞增)
部分填充的有效數獨,不需要填充
細節分析題:
(1)檢查行
(2)檢查列
(3)檢查9個子宮格
代碼實現
使用HashSet:
class Solution {
public boolean isValidSudoku(char[][] board) {
for (int i = 0; i < 9; i++) {
Set<Character> row = new HashSet<Character>();
Set<Character> col = new HashSet<Character>();
Set<Character> cube = new HashSet<Character>();
for (int j = 0; j < 9; j++) {
// 檢查第i行,在橫坐標位置
if (board[i][j] != '.' && !row.add(board[i][j])) {
return false;
}
// 檢查第i行,在橫坐標位置
if (board[j][i] != '.' && ! col.add(board[j][i])) {
return false;
}
// 行號+偏移量
int rowIndex = 3 * (i / 3) + j / 3;
// 列號+偏移量
int colIndex = 3 * (i % 3) + j % 3;
// 每個九宮格,共9個
if (board[rowIndex][colIndex] != '.' && ! cube.add(board[rowIndex][colIndex])) {
return false;
}
}
}
return true;
}
}