Leetcode 解數獨
阿新 • • 發佈:2021-01-31
技術標籤:leetcode題集leetcode
解數獨
題目描述:
編寫一個程式,通過填充空格來解決數獨問題。
一個數獨的解法需遵循如下規則:
數字 1-9 在每一行只能出現一次。
數字 1-9 在每一列只能出現一次。
數字 1-9 在每一個以粗實線分隔的 3x3 宮內只能出現一次。
提示:
1.給定的數獨序列只包含數字 1-9 和字元 '.' 。
2.你可以假設給定的數獨只有唯一解。
3.給定數獨永遠是 9x9 形式的。
空白格用 '.' 表示。
以下答案標記為紅色。
class Solution {
private boolean[][] digit;
private char[][] result;
private boolean[][] row;
private boolean[][] col;
private boolean[][] block;
private boolean end;
public void solveSudoku(char[][] board) {
// 回溯演算法
// 初始化
this.digit = new boolean[9][9];
this.result = board;
this. row = new boolean[9][10];
this.col = new boolean[9][10];
this.block = new boolean[9][10];
for(int i = 0 ; i<9 ;i++){
for(int j = 0 ; j<9 ;j++){
if(board[i][j] != '.'){
int temp = (int)(board[i][j] - '0');
row[ i][temp] = true;
col[j][temp] = true;
block[3*(i/3)+j/3][temp] = true;
digit[i][j] = true;
}
}
}
DFS(0,0); // 從第一行第一列開始
}
public void DFS(int x,int y){
if(x<8 && y == 9){
DFS(x+1,0);
return;
}
if(x == 8 && y == 9){
end = true;
return;
}
for(int i=1 ; i<=9 && !end; i++){ // 遍歷當前位置需要填入的值 這裡有坑:一定注意end標記要放再這裡!否則會被覆蓋修改!
if(!digit[x][y]){ // 當前位置不為固定數字
if(check(x,y,i)){ // 判斷當前位置是否符合規則
row[x][i] = true;
col[y][i] = true;
block[3*(x/3)+y/3][i] = true;
result[x][y] = (char)(i+'0');
DFS(x,y+1); // 對下一列空格位置遞迴
row[x][i] = false;
col[y][i] = false;
block[3*(x/3)+y/3][i] = false;
}
}else{ // 當前位置為固定數字
DFS(x,y+1);
return;
}
}
}
public boolean check(int r,int c,int n){
if(row[r][n] || col[c][n] || block[3*(r/3)+c/3][n]){ // 行判斷、列判斷和塊判斷
return false;
}
return true;
}
}
能簡單地想到,這是一個典型的回溯法例題,首先按照行優先,每次對一個空格進行1到9的遍歷,如果不符合規則,則繼續遍歷剩餘的數字,否則對下一個空格再次執行同樣的操作,當達到結束條件時。第一個需要注意地是:每次的當前規則都要還原操作;第二個需要注意地是:這個結束體一定只能執行一次!否則會發生覆蓋!所以要在for上新增提前結束的條件,而不能在for迴圈外面。如果讀者對回溯演算法還是有些偏難理解,可以先嚐試徹底解決八皇后問題,因為一般的回溯演算法都是八皇后問題的變體,只要掌握了八皇后問題,一般這樣的問題就都能迎刃而解。