LeetCode 37. 解數獨
阿新 • • 發佈:2021-01-02
描述
編寫一個程式,通過填充空格來解決數獨問題。
一個數獨的解法需遵循如下規則:
數字 1-9 在每一行只能出現一次。
數字 1-9 在每一列只能出現一次。
數字 1-9 在每一個以粗實線分隔的 3x3 宮內只能出現一次。
空白格用 ‘.’ 表示。
一個數獨。
答案被標成紅色。
提示:
- 給定的數獨序列只包含數字 1-9 和字元 ‘.’ 。
- 你可以假設給定的數獨只有唯一解。
- 給定數獨永遠是 9x9 形式的。
思路
- 這道題做了一天沒解出來…哎,好難,最終還是看了答案。
- 解數獨是回溯演算法的經典應用。這道題要注意題設一點:答案唯一。也就是說,回溯時只要找到一個答案,程式就可以結束了。為了達到此目的,將回溯函式返回值設為bool,當找到答案時返回true,不再繼續遞迴。
- 從第0行0列開始遍歷,先遍歷第0行的每一列,然後遍歷第1行的每一列…如此直到row=9時超出網格範圍,遞迴結束。
- 對於某些網格,如果為空,才從1~9開始遍歷往裡填,如果已經有值了,那麼直接跳過此格子,進入本行的下一個格子。
- 需要寫一個函式,判斷當前格子的同行、同列,本宮(3x3格子)內是否已經有此元素,沒有才能放,有的話跳過。
解答
class Solution {
public:
void solveSudoku(vector<vector<char>>& board) {
backTrack(board, 0, 0);//從第0行0列開始遞迴
}
bool backTrack(vector<vector<char>>& board, int row, int column){
if(row == 9) return true;//row=9說明找到了正確結果
if(column == 9)
return backTrack(board, row + 1, 0);//column=9,則開始下一行,必須return,否則下面程式碼還會執行
if(board[row][column] == '.'){
for (char i = '1';i <= '9'; ++ i){
if(isInBoard(board, row, column, i) == false){//當前數可填入
board[row][column] = i;
if(backTrack(board, row, column + 1)) return true;//找到結果,結束程式
board[row][column] = '.';
}
}
}else{
//本層得到後續遞迴的結果拋給上一層,不return會執行下面的return false,將false拋給上層
return backTrack(board, row, column + 1);
}
return false;//能執行到這步,說明遍歷完1~9也沒找到合適的數,則失敗。
}
//查詢某個數是否已經在本行、本列、本宮記憶體在,已存在則返回true
bool isInBoard(vector<vector<char>>& board, int row, int column, char target){
for(int k = 0;k < 9; ++ k){
if(board[row][k] == target || board[k][column] == target ||
board[(row / 3) * 3 + k / 3][(column / 3) * 3 + k % 3] == target)
return true;
}
return false;
}
};