一、题目描述
编写一个程序,通过填充空格来解决数独问题。
数独的解法需遵循如下规则:
- 数字
1-9
在每一行只能出现一次。 - 数字
1-9
在每一列只能出现一次。 - 数字
1-9
在每一个以粗实线分隔的3x3
宫内只能出现一次。 - 数独部分空格内已填入了数字,空白格用
'.'
表示。
示例一:
输入:board =
[
["5", "3", ".", ".", "7", ".", ".", ".", "."],
["6", ".", ".", "1", "9", "5", ".", ".", "."],
[".", "9", "8", ".", ".", ".", ".", "6", "."],
["8", ".", ".", ".", "6", ".", ".", ".", "3"],
["4", ".", ".", "8", ".", "3", ".", ".", "1"],
["7", ".", ".", ".", "2", ".", ".", ".", "6"],
[".", "6", ".", ".", ".", ".", "2", "8", "."],
[".", ".", ".", "4", "1", "9", ".", ".", "5"],
[".", ".", ".", ".", "8", ".", ".", "7", "9"]
]
输出:
[
["5", "3", "4", "6", "7", "8", "9", "1", "2"],
["6", "7", "2", "1", "9", "5", "3", "4", "8"],
["1", "9", "8", "3", "4", "2", "5", "6", "7"],
["8", "5", "9", "7", "6", "1", "4", "2", "3"],
["4", "2", "6", "8", "5", "3", "7", "9", "1"],
["7", "1", "3", "9", "2", "4", "8", "5", "6"],
["9", "6", "1", "5", "3", "7", "2", "8", "4"],
["2", "8", "7", "4", "1", "9", "6", "3", "5"],
["3", "4", "5", "2", "8", "6", "1", "7", "9"]
]
二、题解
通过回溯法求解,整体思路与N皇后问题相似,都是依次处理每个格子,同时通过一个 isValid
函数判断当前位置填充值的有效性。
同时因为题目中已经说明题目数据保证输入数独有且仅有一个解,因此我们需要让回溯函数返回值为布尔类型,这样只要遇到任意一种成功的情况,就立即依次返回。
class Solution {
public:
void solveSudoku(vector<vector<char>> &board) {
backtracking(board, 0, 0);
}
private:
bool backtracking(vector<vector<char>> &board, int row, int col) {
if (row == board.size()) {
return true;
}
if (board.at(row).at(col) == '.') {
for (int i = 1; i <= 9; i++) {
board.at(row).at(col) = static_cast<char>(i + 48);
if (isValid(board, row, col)) {
if (col == board.size() - 1) {
if (backtracking(board, row + 1, 0)) {
return true;
}
} else {
if (backtracking(board, row, col + 1)) {
return true;
}
}
}
}
board.at(row).at(col) = '.';
} else {
if (col == board.size() - 1) {
if (backtracking(board, row + 1, 0)) {
return true;
}
} else {
if (backtracking(board, row, col + 1)) {
return true;
}
}
}
return false;
}
bool isValid(vector<vector<char>> &board, int row, int col) {
char c = board.at(row).at(col);
/* 检查列重复 */
for (int i = 0; i < board.size(); i++) {
if (board.at(i).at(col) == c && i != row) {
return false;
}
}
/* 检查行重复 */
for (int j = 0; j < board.size(); j++) {
if (board.at(row).at(j) == c && j != col) {
return false;
}
}
/* 检查组内重复 */
for (int i = (row / 3) * 3; i < ((row / 3) + 1) * 3; i++) {
for (int j = (col / 3) * 3; j < ((col / 3) + 1) * 3; j++) {
if (board.at(i).at(j) == c && i != row && j != col) {
return false;
}
}
}
return true;
}
};