Method 1: DFS (248 ms)
class Solution {
public:
void solveSudoku(vector<vector<char> > &board) {
solveSudoku1(board);
}
bool solveSudoku1(vector<vector<char> > &board)
{
for(int i=0; i<9; i++)
{
for(int j=0; j<9; j++)
{
if(board[i][j] == '.')
{
for(int k=0; k<9; k++)
{
board[i][j] = '1'+k;
if(isValid(board, i, j) && solveSudoku1(board))
return true;
board[i][j] = '.';
}
return false;
}
}
}
return true;
}
bool isValid(vector<vector<char> > &board, int i, int j)
{
for(int col = 0; col < 9; col++)
if(col != j && board[i][col] == board[i][j])
return false;
for(int row = 0; row < 9; row++)
if(row != i && board[row][j] == board[i][j])
return false;
int gridRow = i/3;
int gridCol = j/3;
for(int row = gridRow*3; row < gridRow*3+3; row++)
{
for(int col = gridCol*3; col < gridCol*3+3; col++)
{
if(row != i && col != j && board[row][col] == board[i][j])
return false;
}
}
return true;
}
};
Method 2: improve the validation method using hash map. ( 100 ms)
class Solution {
public:
int rowhash[9];
int colhash[9];
int blockhash[9];
void solveSudoku(vector<vector<char> > &board) {
memset(rowhash, 0, sizeof(rowhash));
memset(colhash, 0, sizeof(colhash));
memset(blockhash, 0, sizeof(blockhash));
for(int i=0; i<9; i++)
{
for(int j=0; j<9; j++)
{
if(board[i][j] != '.')
{
setMap(board, i, j);
}
}
}
solveSudoku1(board);
}
bool solveSudoku1(vector<vector<char> > &board)
{
for(int i=0; i<9; i++)
{
for(int j=0; j<9; j++)
{
if(board[i][j] == '.')
{
for(int k=0; k<9; k++)
{
board[i][j] = '1'+k;
if(isValid(board, i, j))
{
setMap(board, i, j);
if(solveSudoku1(board)) return true;
resetMap(board, i, j);
}
board[i][j] = '.';
}
return false;
}
}
}
return true;
}
bool isValid(vector<vector<char> > &board, int i, int j)
{
if((rowhash[i] >> (board[i][j]-'1'))&1) return false;
if((colhash[j] >> (board[i][j]-'1'))&1) return false;
int gridRow = i/3;
int gridCol = j/3;
if((blockhash[gridRow*3+gridCol] >> (board[i][j]-'1')) & 1) return false;
return true;
}
void setMap(vector<vector<char> > &board, int i, int j)
{
rowhash[i] |= (1 << (board[i][j]-'1'));
colhash[j] |= (1 << (board[i][j]-'1'));
int gridRow = i/3;
int gridCol = j/3;
blockhash[gridRow*3+gridCol] |= (1 << (board[i][j]-'1'));
}
void resetMap(vector<vector<char> > &board, int i, int j)
{
rowhash[i] &= ~(1 << (board[i][j]-'1'));
colhash[j] &= ~(1 << (board[i][j]-'1'));
int gridRow = i/3;
int gridCol = j/3;
blockhash[gridRow*3+gridCol] &= ~(1 << (board[i][j]-'1'));
}
};
Method 3: non-recursion DFS with stack. (48 ms)
class Solution {
public:
int rowhash[9];
int colhash[9];
int blockhash[9];
void solveSudoku(vector<vector<char> > &board) {
memset(rowhash, 0, sizeof(rowhash));
memset(colhash, 0, sizeof(colhash));
memset(blockhash, 0, sizeof(blockhash));
vector<pair<int, int> > empty;
empty.push_back(make_pair(-1, -1));
for(int i=0; i<9; i++)
{
for(int j=0; j<9; j++)
{
if(board[i][j] != '.')
{
setMap(i, j, (board[i][j]-'0'));
}
else
empty.push_back(make_pair(i,j));
}
}
vector<pair<int, int> > stack;
vector<pair<int, int> > path;
//push back the dummy element index
stack.push_back(make_pair(0, -1));
int idx, val, posX, posY;
while(!stack.empty())
{
idx = stack.back().first;
val = stack.back().second;
path.push_back(make_pair(idx, val));
if(idx > 0)
{
posX = empty[idx].first;
posY = empty[idx].second;
board[posX][posY] = ('0' + val);
setMap(posX, posY, val);
}
if(path.size() == empty.size())
break;
pair<int, int> pos = empty[idx+1];
for(int i=1; i<=9; i++)
{
if(isValid(pos.first, pos.second, i))
stack.push_back(make_pair(idx+1, i));
}
while(!stack.empty() && stack.back() == path.back())
{
idx = path.back().first;
val = path.back().second;
if(idx > 0)
{
posX = empty[idx].first;
posY = empty[idx].second;
board[posX][posY] = '.';
resetMap(posX, posY, val);
}
stack.pop_back();
path.pop_back();
}
}
}
bool isValid(int i, int j, int value)
{
if((rowhash[i] >> value) & 1) return false;
if((colhash[j] >> value) & 1) return false;
if((blockhash[(i/3)*3+j/3] >> value) & 1) return false;
return true;
}
void setMap(int i, int j, int value)
{
rowhash[i] |= (1 << value);
colhash[j] |= (1 << value);
blockhash[(i/3)*3+j/3] |= (1 << value);
}
void resetMap(int i, int j, int value)
{
rowhash[i] &= ~(1 << value);
colhash[j] &= ~(1 << value);
blockhash[(i/3)*3+j/3] &= ~(1 << value);
}
};