37. Sudoku Solver
Write a program to solve a Sudoku puzzle by filling the empty cells.
A sudoku solution must satisfy all of the following rules:
- Each of the digits
1-9must occur exactly once in each row. - Each of the digits
1-9must occur exactly once in each column. - Each of the the digits
1-9must occur exactly once in each of the 93x3sub-boxes of the grid.
Empty cells are indicated by the character '.'.

A sudoku puzzle...

...and its solution numbers marked in red.
Note:
- The given board contain only digits
1-9and the character'.'. - You may assume that the given Sudoku puzzle will have a single unique solution.
- The given board size is always
9x9.
题目链接:https://leetcode.com/problems/sudoku-solver/
心路历程
刚看到题目的思路很复杂,想着能联系上一道题,一边记录遍历,一边通过判断在记录里是否符合规则而选择数字。
事实证明果然想复杂了,复杂度高,还不可行。
直接带入原数据里去挨个判断就好。
方法:回溯法
class Solution {
public:
void solveSudoku(vector<vector<char>>& board) {
fill(board);
}
int fill(vector<vector<char>>& board){
for(int i=0; i<9; ++i){
for(int j=0; j<9; ++j){
int num = 1;
if(board[i][j]-'0' == '.'-'0'){
while(num<=9){
if(isValid(board, i, j, num)){
board[i][j] = '0'+num;
if(fill(board)){
return true;
}else{
board[i][j] = '.';
}
}
++num;
}
return false;
}
}
}
return true;
}
bool isValid(vector<vector<char>>& board, int i, int j, int num){
for (int l=0; l<9; ++l){
if(board[i][l]-'0'==num) return false;
if(board[l][j]-'0'==num) return false;
}
int startL = int(i/3) *3;
int startC = int(j/3) *3;
for (int l = startL; l<startL+3; ++l){
for(int c = startC; c<startC+3; ++c){
if(board[l][c]-'0'==num)return false;
}
}
return true;
}
};
在运行时间上优化
记录当前遍历得到的位置,则在回溯的时候能直接跳到该位置,而不用重新再遍历一次前面已经遍历过的元素。
以下代码来自网友:https://www.cnblogs.com/ganganloveu/p/3828401.html
class Solution {
public:
void solveSudoku(vector<vector<char> > &board) {
solve(board, 0);
}
bool solve(vector<vector<char> > &board, int position)
{
if(position == 81)
return true;
int row = position / 9;
int col = position % 9;
if(board[row][col] == '.')
{
for(int i = 1; i <= 9; i ++)
{//try each digit
board[row][col] = i + '0';
if(check(board, position))
if(solve(board, position + 1))
//only return valid filling
return true;
board[row][col] = '.';
}
}
else
{
if(solve(board, position + 1))
//only return valid filling
return true;
}
return false;
}
bool check(vector<vector<char> > &board, int position)
{
int row = position / 9;
int col = position % 9;
int gid;
if(row >= 0 && row <= 2)
{
if(col >= 0 && col <= 2)
gid = 0;
else if(col >= 3 && col <= 5)
gid = 1;
else
gid = 2;
}
else if(row >= 3 && row <= 5)
{
if(col >= 0 && col <= 2)
gid = 3;
else if(col >= 3 && col <= 5)
gid = 4;
else
gid = 5;
}
else
{
if(col >= 0 && col <= 2)
gid = 6;
else if(col >= 3 && col <= 5)
gid = 7;
else
gid = 8;
}
//check row, col, subgrid
for(int i = 0; i < 9; i ++)
{
//check row
if(i != col && board[row][i] == board[row][col])
return false;
//check col
if(i != row && board[i][col] == board[row][col])
return false;
//check subgrid
int r = gid/3*3+i/3;
int c = gid%3*3+i%3;
if((r != row || c != col) && board[r][c] == board[row][col])
return false;
}
return true;
}
};
ps.事实证明对回溯法、递归还不熟练。
todo:看视频加强

本文详细介绍了如何使用回溯法解决数独问题,通过逐个单元格填充数字并检查行、列及3x3子网格的有效性,实现了数独求解器。文章提供了两种不同的C++代码实现,一种直接在原始数据上进行判断,另一种优化了回溯过程,避免重复遍历已知单元格。

1181

被折叠的 条评论
为什么被折叠?



