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 '.'
.
A partially filled sudoku which is valid.
Note:
A valid Sudoku board (partially filled) is not necessarily solvable. Only the filled cells need to be validated.算法
驗證一個數獨棋盤是否合法,數獨棋盤的驗證規則見連接對應的頁面。
數獨棋盤是部分填滿的,空的位置使用點來代替。
注意:合法的棋盤不必定要求的可解的,只要填充的數字知足要求就能夠。數組
先對行進行檢查,再對列進行檢查,最後檢查3*3的方格。spa
算法實現類.net
public class Solution { public boolean isValidSudoku(char[][] board) { // .的ASCII值是46,0的ASCII值是48,/的ASCII值是47 int number = board[0].length; int[] record = new int[10 + 2]; //保存.到9的值,保存數據的位置在[2, 10] boolean isValid; reset(record); // 對行進行檢查 for (int i = 0; i < number; i++) { for (int j = 0; j < number; j++) { record[board[i][j] - '.']++; } if (!check(record)) { // 如是檢查失敗 return false; } else { // 檢查成功重置棋盤 reset(record); } } // 對列進行檢查 for (int i = 0; i < number; i++) { for (int j = 0; j < number; j++) { record[board[j][i] - '.']++; } if (!check(record)) { // 如是檢查失敗 return false; } else { // 檢查成功重置棋盤 reset(record); } } // 檢查3*3方塊 for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { for (int k = i * 3; k < (i + 1) * 3; k++) { for (int l = j * 3; l < (j + 1) * 3; l++) { record[board[k][l]- '.']++; } } if (!check(record)) { // 如是檢查失敗 return false; } else { // 檢查成功重置棋盤 reset(record); } } } return true; } private void reset(int[] a) { for (int i = 0; i < a.length; i++) { a[i] = 0; } } /** * 檢查棋盤一行,一列,或者3*3的方格是否合法,若是1-9中的數字個數大於1就不合法 * * @param a 驗證數字 * @return 返回結果 */ private boolean check(int[] a) { for (int i = 2; i < a.length; i++) { if (a[i] > 1) { return false; } } return true; } }
數獨問題描述code
標準的數獨遊戲是在一個 9 X 9 的棋盤上填寫 1 – 9 這 9 個數字,規則是這樣的:遞歸
- 棋盤分紅上圖所示的 9 個區域(不一樣顏色作背景標出,每一個區域是 3 X 3 的子棋盤),在每一個子棋盤中填充 1 – 9 且不容許重複 ,下面簡稱塊重複
- 每一行不準有重複值 ,下面簡稱行重複
- 每一列不準有重複值 ,下面簡稱列重複
如上紅色框出的子區域中的亮黃色格子只能填 8。遊戲
解決思路一描述:圖片
1.使用二維數組表示數獨,不肯定的數使用0填充。get
2.從位置(0,0)開始遍歷二維數組。it
3.跳過已肯定的數字,直到找到第一個不肯定的數(即數值0)。若是找不到不肯定的數字,則表示數獨已填充完成。
4.根據當前數值0的位置,排除到同行、同列、同一個小宮格中已經出現的數字,獲得當前位置全部容許填充的數字。
5.若是不存在容許填充的數字,則當前數獨無解。
6.嘗試填充每個容許的數字,並遞歸填充下一個不肯定的數字。
7.若是遞歸填充成功,返回成功。
8.若是遞歸填充失敗,回退步驟6中填充的數字,並跳轉到6繼續嘗試下一個容許的數字。
相關代碼後續補充。
缺點:數獨中每個未肯定的值都須要遞歸窮舉,最大的遞歸層級等於未肯定值的數目。
改進方式:每填充一個值,在遞歸填充以前,動態計算每一個待填充值的候選數字,刪除再也不符合規則的候選數字。若是有位置的候選數字爲空,則數獨無解。若是有位置的候選數字只有惟一一個,則直接填充該數字。經過上述兩種方式能夠有效減小遞歸的層次。