This commit is contained in:
Sainnhe Park 2022-11-22 17:24:36 +08:00
parent d40423a898
commit 9a6595462d
3 changed files with 123 additions and 0 deletions

View File

@ -0,0 +1,16 @@
#ifndef S0037_SUDOKU_SOLVER_HPP
#define S0037_SUDOKU_SOLVER_HPP
#include <vector>
#include <unordered_map>
#include <cmath>
#include <algorithm>
using namespace std;
class Solution {
public:
void solveSudoku(vector<vector<char>>& board);
};
#endif

View File

@ -0,0 +1,80 @@
#include "s0037_sudoku_solver.hpp"
#include <unordered_map>
#include <vector>
// 返回结果为当前传递进去的数独是否存在解
bool recusiveSolveSudoku(vector<vector<char>> &board,
vector<unordered_map<char, bool>> &rows,
vector<unordered_map<char, bool>> &cols,
vector<unordered_map<char, bool>> &grids, int row,
int col) {
int size = board.size();
// 边界校验
if (col == size) {
// 进入下一行
col = 0;
row++;
// 填充完成,返回 True
if (row == size) {
return true;
}
}
// 如果不为空则跳过,填充下一个
if (board[row][col] != '.') {
return recusiveSolveSudoku(board, rows, cols, grids, row, col + 1);
} else { // 否则开始填充
// 尝试填充 1 ~ 9
for (char num{'1'}; num <= '9'; ++num) {
int gridIndex = static_cast<int>(floor(row / 3)) +
3 * static_cast<int>(floor(col / 3));
// 如果这个数字还没有出现过
if (!(rows[row].count(num) == 1 || cols[col].count(num) == 1 ||
grids[gridIndex].count(num) == 1)) {
// 先把这个数字填进去
rows[row][num] = true;
cols[col][num] = true;
grids[gridIndex][num] = true;
board[row][col] = num;
// 然后试试看填进去后下一个能不能解
// 如果下一个能解的话,现在这个肯定能解
if (recusiveSolveSudoku(board, rows, cols, grids, row, col + 1)) {
return true;
}
// 如果不能解,那么说明这个数字填错了,把它重新设为空,然后尝试下一个数字
board[row][col] = '.';
rows[row].erase(num);
cols[col].erase(num);
grids[gridIndex].erase(num);
}
}
}
return false;
}
void Solution::solveSudoku(vector<vector<char>> &board) {
// 每个行/列/单元格中某个数字是否出现过
vector<unordered_map<char, bool>> rows;
vector<unordered_map<char, bool>> cols;
vector<unordered_map<char, bool>> grids;
// 初始化
int size = board.size();
for (int i{0}; i < size; ++i) {
rows.push_back(unordered_map<char, bool>{});
cols.push_back(unordered_map<char, bool>{});
grids.push_back(unordered_map<char, bool>{});
}
for (int row{0}; row < size; ++row) {
for (int col{0}; col < size; ++col) {
if (board[row][col] != '.') {
rows[row][board[row][col]] = true;
cols[col][board[row][col]] = true;
int gridIndex = static_cast<int>(floor(row / 3)) +
3 * static_cast<int>(floor(col / 3));
grids[gridIndex][board[row][col]] = true;
}
}
}
// 从 (0, 0) 开始递归求解
recusiveSolveSudoku(board, rows, cols, grids, 0, 0);
}

View File

@ -0,0 +1,27 @@
#include "s0037_sudoku_solver.hpp"
#include <gtest/gtest.h>
TEST(Problem37, Case1) {
vector<vector<char>> 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'}};
vector<vector<char>> expected{{'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'}};
Solution solution;
solution.solveSudoku(board);
EXPECT_EQ(board, expected);
}