题目链接:LeetCode 37. 解数独
题意:
编写一个程序,通过已填充的空格来解决数独问题。
一个数独的解法需遵循如下规则:
- 数字
1-9
在每一行只能出现一次。 - 数字
1-9
在每一列只能出现一次。 - 数字
1-9
在每一个以粗实线分隔的3x3
宫内只能出现一次。
空白格用 '.'
表示。
解题思路:
dfs递归查找,需要记录某一行出现的数字,某一列出现的数字,某个块中出现的数字。如果出现过,标记true。
然后依次查询,如果不满足,就重新,标记为false
class Solution {
private:
bool line[9][9]; // 行
bool column[9][9]; // 列
bool block[3][3][9]; // 块
bool valid; // 判断整体是否合法
vector<pair<int, int>> spaces; // 存数组中为空的位置
public:
void dfs(vector<vector<char>>& board, int num) {
if(num == spaces.size()) { // 如果所有数被填入数组中,那么结束
valid = true;
return ;
}
int i = spaces[num].first;
int j = spaces[num].second;
for(int digit = 0; digit < 9 && !valid; digit++) { // 查看是否全部被填,如果已经满足,不再递归
if(!line[i][digit] && !column[digit][j] && !block[i/3][j/3][digit]) {
line[i][digit] = column[digit][j] = block[i/3][j/3][digit] = true;
board[i][j] = digit + '0' + 1;
dfs(board, num+1);
line[i][digit] = column[digit][j] = block[i/3][j/3][digit] = false;
}
}
}
void solveSudoku(vector<vector<char>>& board) {
memset(line, false, sizeof(line));
memset(column, false, sizeof(column));
memset(block, false, sizeof(block));
valid = false; // 初始化
for(int i = 0; i < 9; i++) {
for(int j = 0; j < 9; j++) {
if(board[i][j] == '.') {
spaces.emplace_back(i, j); // 如果为 . 那么需要对当前位置进行判断
} else {
int digit = board[i][j] - '0' - 1; // 记录当前位置的数,因为数组下标从0开始,所以此处多减一
line[i][digit] = column[digit][j] = block[i/3][j/3][digit] = true; // 当前行,列,块这个数字已经被使用
}
}
}
dfs(board, 0);
}
};