1 題目描述
編寫一個程序,通過已填充的空格來解決數獨問題。一個數獨的解法需遵循如下規則:
- 數字 1-9 在每一行只能出現一次。
- 數字 1-9 在每一列只能出現一次。
- 數字 1-9 在每一個以粗實線分隔的 3x3 宮內只能出現一次。
- 空白格用 ‘.’ 表示。
Note:
- 給定的數獨序列只包含數字
1-9
和字符'.'
。 - 你可以假設給定的數獨只有唯一解。
- 給定數獨永遠是
9x9
形式的。
2 題解
解數獨基本沒有特別好的方法,讓笨笨的計算機去解數獨它只會回溯。大致的思路:遞歸求解數獨就按照從左往右從上往下的順序逐個試過去,如果不符合數獨的規則則回溯到上一個狀態。
小trick
在進行回溯之前,先遍歷一遍數獨矩陣,將空位置的座標記下來,在回溯的時候逐個訪問空座標。話不多說,直接看代碼吧:
C++代碼
class Solution {
public:
bool check(vector<vector<char>> & board, int row, int col) {
// check row
for (int i = 0; i < 9; i++)
if (i != col && board[row][i] == board[row][col]) return false;
// check col
for (int i = 0; i < 9; i++)
if (i != row && board[i][col] == board[row][col]) return false;
// check block
for (int i = (col / 3) * 3; i < (col / 3) * 3 + 3; i++) {
for (int j = (row / 3) * 3; j < (row / 3) * 3 + 3; j++) {
if (i != col && j != row && board[j][i] == board[row][col]) return false;
}
}
return true;
}
bool helper(vector<vector<char>>& board, vector<int> &blank_list, int index) {
if (index == blank_list.size()) {
return true;
}
int row = blank_list[index] / 9;
int col = blank_list[index] % 9;
bool ret = false;
for (int i = 1; i <= 9; i++) {
board[row][col] = '0' + i;
if (ret == false && check(board, row, col))
ret = helper(board, blank_list, index + 1);
if (ret == true)
return true;
board[row][col] = '.';
}
return false;
}
void solveSudoku(vector<vector<char>>& board) {
vector<int> blank_list;
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if (board[i][j] == '.') blank_list.push_back(i * 9 + j);
}
}
helper(board, blank_list, 0);
}
};