Write a program to solve a Sudoku puzzle by filling the empty cells.
Empty cells are indicated by the character '.'.
You may assume that there will be only one unique solution.
![]()
A sudoku puzzle...
![]()
...and its solution numbers marked in red.
Have you been asked this question in an interview?
首先leetcode只要求9*9的输入,所以不可能出现时间和空间不够用的问题。
基本思路是回溯,回溯类似就是DFS,不同的是某层失败后要回到上一层,失败的一层要恢复原样。
另外,回溯也要使用递归,递归需要有收敛条件,就是要有一段code,不会调用自身而返回。
这里的关键点是对于一旦出现解出现的情况,要防止递归函数返回后修改数据,所以要标记解出现的情况,可以用返回值或全局变量标记:
全局变量:
bool flag= false;
bool check(int k, vector<vector<char> > &board){
int x=k/9;
int y=k%9;
for (int i = 0; i < 9; i++)
if (i != x && board[i][y] == board[x][y])
return false;
for (int j = 0; j < 9; j++)
if (j != y && board[x][j] == board[x][y])
return false;
for (int i = 3 * (x / 3); i < 3 * (x / 3 + 1); i++)
for (int j = 3 * (y / 3); j < 3 * (y / 3 + 1); j++)
if (i != x && j != y && board[i][j] == board[x][y])
return false;
return true;
}
void dfs(int num,vector<vector<char> > &board){
if(num==81){
flag=true;
return;
}
else{
int x=num/9;
int y=num%9;
if(board[x][y]=='.'){
for(int i=1;i<=9;i++){
board[x][y]=i+'0';
if(check(num,board)){
dfs(num+1,board);
if(flag)
return;
}
}
board[x][y]='.';
}
else{
dfs(num+1,board);
}
}
}
void solveSudoku(vector<vector<char> > &board) {
dfs(0,board);
}返回值:
int n,m;
bool check(int k, vector<vector<char> > &board){
int x=k/n;
int y=k%m;
for (int i = 0; i < n; i++)
if (i != x && board[i][y] == board[x][y])
return false;
for (int j = 0; j < m; j++)
if (j != y && board[x][j] == board[x][y])
return false;
for (int i = 3 * (x / 3); i < 3 * (x / 3 + 1); i++)
for (int j = 3 * (y / 3); j < 3 * (y / 3 + 1); j++)
if (i != x && j != y && board[i][j] == board[x][y])
return false;
return true;
}
bool f(int i, vector<vector<char> > &board){
if(i==n*m)
return true;
if(board[i/n][i%m]=='.'){
for(int k=1;k<=9;k++){
board[i/n][i%m]=k+'0';
if(check(i,board) && f(i+1,board))
return true;
}
board[i/n][i%m]='.';
return false;
}
else
return f(i+1,board);
}
void solveSudoku(vector<vector<char> > &board) {
n=board.size();
m=board[0].size();
f(0,board);
}上面两个都是得到一个解就返回,还有是可以得到所有解的情况,也就是在解出现的时候存下来。
vector<vector<vector<char> >> sum;
bool check(int k, vector<vector<char> > &board){
int x=k/9;
int y=k%9;
for (int i = 0; i < 9; i++)
if (i != x && board[i][y] == board[x][y])
return false;
for (int j = 0; j < 9; j++)
if (j != y && board[x][j] == board[x][y])
return false;
for (int i = 3 * (x / 3); i < 3 * (x / 3 + 1); i++)
for (int j = 3 * (y / 3); j < 3 * (y / 3 + 1); j++)
if (i != x && j != y && board[i][j] == board[x][y])
return false;
return true;
}
void dfs(int num,vector<vector<char> > &board){
if(num==81){
sum.push_back(board);
return;
}
else{
int x=num/9;
int y=num%9;
if(board[x][y]=='.'){
for(int i=1;i<=9;i++){
board[x][y]=i+'0';
if(check(num,board)){
dfs(num+1,board);
//if(flag)
// return;
}
}
board[x][y]='.';
}
else{
dfs(num+1,board);
}
}
}
void solveSudoku(vector<vector<char> > &board) {
dfs(0,board);
}
int main()
{
vector<string> myboard({"...748...","7........",".2.1.9...","..7...24.",".64.1.59.",".98...3..","...8.3.2.","........6","...2759.."});
vector<char> temp(9,'.');
vector<vector<char> > board(9,temp);
for(int i=0;i<myboard.size();i++){
for(int j=0;j<myboard[i].length();j++){
board[i][j]=myboard[i][j];
}
}
solveSudoku(board);
for(int k=0;k<sum.size();k++){
for(int i=0;i<sum[k].size();i++){
for(int j=0;j<sum[k][i].size();j++){
cout<<sum[k][i][j]<<" ";
}
cout<<endl;
}
cout<<"######"<<endl;
}
cout<<"sum is "<<sum.size()<<endl;
cout << "Hello world!" << endl;
return 0;
}输出了8个解。
本文介绍了一个用于解决数独谜题的回溯算法实现,通过递归和检查函数来填充空格,确保唯一解的存在。讨论了算法的时间复杂度、空间复杂度以及如何优化解决方案的数量。
400

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



