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.
class Solution {
public:
void solveSudoku(vector > &board) {
internalSolveSudoku(board);
}
private:
bool internalSolveSudoku(vector > &board){
for(int row = 0; row < 9; ++row){
for(int col = 0; col < 9; ++col){
if('.' == board[row][col]){//该格未填值
for(int k = 1; k <=9; ++k){//尝试填入1到9
board[row][col] = '0' + k;
if(check(board, row, col)){//检查在第row行第col列填入k是否合法
if(internalSolveSudoku(board)){//若合法,尝试填下一空
return true;//找到解
}
}//if(check(board, row, col))
board[row][col] = '.';//若不合法,清除k
}//for(int k = 1; k <=9; ++k)
return false;
}//if('.' == board[row][col])
}//for(int col = begin_col; col < 9; ++col)
}//for(int row = 0; row < 9; ++row)
return true;//找到解
}
bool check(vector > &board, int row, int col){
//检查第row行是否有重复
for(int i = 0; i < 9; ++i){
if(i != col && board[row][i] == board[row][col]){
return false;//发现重复
}
}
//检查第col列是否有重复
for(int i = 0; i < 9; ++i){
if(i != row && board[i][col] == board[row][col]){
return false;//发现重复
}
}
//检查第row行第col列所在的3*3方格是否有重复
int begin_row_block = row / 3 * 3;//3*3方格的开始行号
int begin_col_block = col / 3 * 3;//3*3方格的开始列号
int end_row_block = begin_row_block + 3;//3*3方格的结束行号
int end_col_block = begin_col_block + 3;//3*3方格的结束列号
for(int i = begin_row_block; i < end_row_block; ++i){
for(int j = begin_col_block; j < end_col_block; ++j){
if((i != row || j != col) && board[i][j] == board[row][col]){
return false;//发现重复
}
}
}
return true;//无重复
}
};
class Solution {
public:
void solveSudoku(vector > &board) {
internalSolveSudoku(board, 0, 0);
}
private:
bool internalSolveSudoku(vector > &board, int begin_row, int begin_col){
int row = begin_row;
int col = begin_col;
while(row < 9){
if('.' == board[row][col]){
for(int k = 1; k <=9; ++k){
board[row][col] = '0' + k;
if(check(board, row, col)){
if(col < 8){
if(internalSolveSudoku(board, row, col+1)){
return true;
}
}//if(col < 8)
else{
if(internalSolveSudoku(board, row + 1, 0)){
return true;
}
}//else
}//if(check(board, row, col))
board[row][col] = '.';
}//for(int k = 1; k <=9; ++k)
return false;
}//if('.' == board[row][col])
++col;
if(col > 8){
col = 0;
++row;
}
}//while(row < 9)
return true;
}
//检查函数同解法1
bool check(vector > &board, int row, int col){
//check row
for(int i = 0; i < 9; ++i){
if(i != col && board[row][i] == board[row][col]){
return false;
}
}
//check column
for(int i = 0; i < 9; ++i){
if(i != row && board[i][col] == board[row][col]){
return false;
}
}
//check the 3*3 block
int begin_row_block = row / 3 * 3;
int begin_col_block = col / 3 * 3;
int end_row_block = begin_row_block + 3;
int end_col_block = begin_col_block + 3;
for(int i = begin_row_block; i < end_row_block; ++i){
for(int j = begin_col_block; j < end_col_block; ++j){
if((i != row || j != col )&& board[i][j] == board[row][col]){
return false;
}
}
}
return true;
}
};
class Solution {
public:
void solveSudoku(vector > &board) {
vector b;//b[i]为true,表示数字‘i+1’还未使用。例如若b[0]为true,则表示数字‘1’未使用。
b.assign(9, true);
column_left_.assign(9,b);
line_left_.assign(9,b);
sub_box_left_.assign(9,b);
int sub_box_order = 0;
int n = 0;
for(int i = 0; i < 9; ++i){
for(int j = 0; j < 9; ++j){
if(board[i][j] != '.'){
n = board[i][j] - '1';
line_left_[i][n] = false;
column_left_[j][n] = false;
sub_box_order = i / 3 * 3 + j / 3;//由行号列号得到3*3表方格的编号
sub_box_left_[sub_box_order][n] = false;
}//if(board[i][j] != '.')
}//for(int j = 0; j < 9; ++j)
}//for(int i = 0; i < 9; ++i)
internalSolveSudoku(board, 0, 0);
}
private:
bool internalSolveSudoku(vector > &board, int begin_row, int begin_col){
int row = begin_row;
int col = begin_col;
while(row < 9){
if('.' == board[row][col]){
int sub_box_order = row / 3 * 3 + col / 3;
for(int k = 0; k < 9; ++k){
if(line_left_[row][k] && column_left_[col][k] && sub_box_left_[sub_box_order][k]){//数字‘k+1’尚未使用,即填入数字‘k+1’不会引起冲突
board[row][col] = '1' + k;
line_left_[row][k] = false;
column_left_[col][k] = false;
sub_box_left_[sub_box_order][k] = false;
if(col < 8){
if(internalSolveSudoku(board, row, col+1)){
return true;
}
}//if(col < 8)
else{
if(internalSolveSudoku(board, row + 1, 0)){
return true;
}
}//else
board[row][col] = '.';
line_left_[row][k] = true;
column_left_[col][k] = true;
sub_box_left_[sub_box_order][k] = true;
}//if(line_left_[row][k] && column_left_[col][k] && sub_box_left_[sub_box_order][k])
}//for(int k = 1; k <=9; ++k)
return false;
}//if('.' == board[row][col])
++col;
if(col > 8){
col = 0;
++row;
}
}//while(row < 9)
return true;
}
vector> line_left_;//每行剩下可以填的数字,一共9行,每行有9个bool值
vector> column_left_;//每列剩下可以填的数字,一共9列,每列有9个bool值
vector> sub_box_left_;//每个3*3的小方格可以填的数字,一共9个方格,每个方格有9个bool值
};
算法 |
时间 |
1 |
236ms |
2 |
192ms |
3 |
124ms |