索引:[LeetCode] Leetcode 题解索引 (C++/Java/Python/Sql)
Github: https://github.com/illuz/leetcode
题目:https://leetcode.com/problems/sudoku-solver/
代码(github):https://github.com/illuz/leetcode
求解一个数独。
DFS 暴力就行了。
用二进制表示,位运算处理的话,会快很多的。
其实在一个 (n^2) * (n^2)
的格中放 n * n
数,这是个 NP 难问题,就 9x9 的方格,就有9^81
种组合,用 DFS 遍历一遍是不可想象的,所以在解一个空一点的 9x9 时就要跑好久。
有个比较常用的优化方法就是用 Dancing Links
,不过这也只是个剪枝,它仍是个 NP 难问题。
Link:
- Sudoku - Wikipedia
- Dancing Links
C++:
class Solution { private: int row[9], col[9], sqr[3][3]; bool check(int x, int y, int val) { return !((row[x]>>val)&1) && !((col[y]>>val)&1) && !((sqr[x/3][y/3]>>val)&1); } void mark(int x, int y, int val, vector<vector<char> > &board) { row[x] |= (1<<val); col[y] |= (1<<val); sqr[x/3][y/3] |= (1<<val); board[x][y] = val + '1'; } void unmark(int x, int y, int val, vector<vector<char> > &board) { row[x] -= (1<<val); col[y] -= (1<<val); sqr[x/3][y/3] -= (1<<val); board[x][y] = '.'; } bool dfs(int pos, vector<vector<char> > &board) { // x = pos / 9, y = pos % 9 if (pos == 81) return true; if (board[pos/9][pos%9] != '.') { return dfs(pos + 1, board); } else { for (int i = 0; i < 9; i++) if (check(pos/9, pos%9, i)) { mark(pos/9, pos%9, i, board); if (dfs(pos + 1, board)) return true; unmark(pos/9, pos%9, i, board); } } return false; } public: void solveSudoku(vector<vector<char> > &board) { memset(row, 0, sizeof(row)); memset(col, 0, sizeof(col)); memset(sqr, 0, sizeof(sqr)); for (int i = 0; i < board.size(); i++) for (int j = 0; j < board[i].size(); j++) if (board[i][j] != '.') { mark(i, j, board[i][j] - '1', board); } dfs(0, board); } };