leetcode专题训练 37. Sudoku Solver

it2022-05-05  143

类似于八皇后问题的回溯法。时间复杂度爆炸,然而能过。我还以为过不了。 这段代码中的精髓段如下。判断是否能将数字i填进去,如果能填就试着填一下。如果成立,就返回1,如果不成立,就把之前用来试着填的状态全部改回初始状态。

if (row[r][i] || col[c][i] || box[boxn][i]) continue; row[r][i] = 1; col[c][i] = 1; box[boxn][i] = 1; board[r][c] = '0' + i; if (solve(now + 1, board, le - 1) == 1) { return 1; } row[r][i] = 0; col[c][i] = 0; box[boxn][i] = 0; board[r][c] = '.';

还需要注意,用了一个vector存储所有空的块的位置,就不用再挨个扫矩阵中的每个元素了,可以直接跳过非空的块。 综上,这道题的解题代码如下:

class Solution { private: int row[10][11], col[10][11], box[10][11]; struct Node{ int r, c, boxn; Node(){} Node(int rr, int cc, int nn) { r = rr; c = cc; boxn = nn; } }; vector<Node> emp; //存储所有空白块的索引 int FindBox(int r, int c) { int tmp_r = r / 3; int tmp_c = c / 3; if (tmp_r == 0) { if (tmp_c == 0) return 0; if (tmp_c == 1) return 1; if (tmp_c == 2) return 2; } if (tmp_r == 1) { if (tmp_c == 0) return 3; if (tmp_c == 1) return 4; if (tmp_c == 2) return 5; } if (tmp_r == 2) { if (tmp_c == 0) return 6; if (tmp_c == 1) return 7; if (tmp_c == 2) return 8; } return -1; } int solve(int now, vector<vector<char>>& board, int le) { if (le == 0) return 1; int r = emp[now].r; int c = emp[now].c; int boxn = emp[now].boxn; for (int i = 1; i <= 9; i++) { if (row[r][i] || col[c][i] || box[boxn][i]) continue; row[r][i] = 1; col[c][i] = 1; box[boxn][i] = 1; board[r][c] = '0' + i; if (solve(now + 1, board, le - 1) == 1) { return 1; } row[r][i] = 0; col[c][i] = 0; box[boxn][i] = 0; board[r][c] = '.'; } return 0; } public: void solveSudoku(vector<vector<char>>& board) { emp.clear(); memset(row, 0, sizeof(row)); memset(col, 0, sizeof(col)); memset(box, 0, sizeof(box)); int le = 0; for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { if (board[i][j] == '.') { le++; emp.push_back(Node(i, j, FindBox(i, j))); continue; } int num = board[i][j] - '0'; row[i][num] = 1; col[j][num] = 1; box[FindBox(i, j)][num] = 1; } } solve(0, board, le); return; } };

最新回复(0)