s0037
This commit is contained in:
parent
d40423a898
commit
9a6595462d
16
include/s0037_sudoku_solver.hpp
Normal file
16
include/s0037_sudoku_solver.hpp
Normal 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
|
80
src/s0037_sudoku_solver.cpp
Normal file
80
src/s0037_sudoku_solver.cpp
Normal 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);
|
||||||
|
}
|
27
tests/s0037_sudoku_solver.cpp
Normal file
27
tests/s0037_sudoku_solver.cpp
Normal 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);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user