今天刷了一道题感觉难度有点大,不过该题的标签是“hard”,下面就和大家分享一下经验吧!
题目如下:
题意分析:
本题为著名的求解数独问题:请为给定的9*9棋盘中‘.’处(可视作图中的空格)填入1-9之间的数字,使得1-9之间的数字在横向、纵向以及3*3的子平面均只出现一次。
注:① 题目给定的棋盘有唯一解 ② 棋盘大小总为9*9
方法一(递归回溯法①)
本题与N-Queens的思路有些相似,均采取“试凑法”。对于棋盘中每个需要填数字的格子均试放从1到9的数,且每放入一个数都通过is_Valid函数来判定其是否合法,如果合法就继续下一次递归,结束时把数字设回'.'。
注:判断新放入的数是否合法时,由于之前加进的数都是合法的,所以只需要判定新放入的数字是否合法即可。
解题代码如下:
class Solution{
private:
bool findsolveSudoku( vector<vector<char>>& board, int i, int j ){
if ( i == 9 ) return true;
if ( j >= 9 ) return findsolveSudoku( board, i+1, 0 );
if( board[i][j] == '.' ){
for ( int k = 1; k < 10; k++ ) {
board[i][j] = (char)(k + '0');
if ( is_Valid( board, i ,j ) ){
if ( findsolveSudoku( board, i, j + 1 ) ) return true;
}
board[i][j] = '.';
}
}
else{
return findsolveSudoku( board, i, j+1 );
}
//数独无解
return false;
}
bool is_Valid( vector<vector<char>>& board, int row ,int col ){
for ( int i = 0; i < 9; i++ ) {
if ( i != col && board[row][i] == board[row][col] ) return false;
}
for ( int i = 0; i < 9; i++ ) {
if ( i != row && board[i][col] == board[row][col] ) return false;
}
for ( int i = row / 3 * 3; i < row / 3 * 3 + 3; i++ ) {
for ( int j = col / 3 * 3; j < col / 3 * 3 +3; j++ ) {
if ( i != row && j != col && board[i][j] == board[row][col]) return false;
}
}
return true;
}
public:
void solveSudoku( vector<vector<char>>& board ){
if ( board.empty() || board.size() != 9 || board[0].size() != 9 ) return;
findsolveSudoku( board, 0, 0 );
}
};
提交后的结果如下:
方法二(递归回溯法②)
这是刘宇波老师在Github(https://github.com/liuyubobobo/Play-Leetcode/tree/master)给出的版本,其实个人还是比较喜欢刘宇波老师讲的课,建议大家可以去听听他讲的《玩转算法面试》。
解题代码如下:
class Solution {
public:
void solveSudoku(vector<vector<char>>& board) {
vector<vector<bool>> row(9, vector<bool>(10, false));
vector<vector<bool>> col(9, vector<bool>(10, false));
vector<vector<bool>> block(9, vector<bool>(10, false));
for(int i = 0; i < 9; i ++)
for(int j = 0; j < 9; j ++)
if(board[i][j] != '.'){
row[i][board[i][j] - '0'] = true;
col[j][board[i][j] - '0'] = true;
block[i / 3 * 3 + j / 3][board[i][j] - '0'] = true;
}
for(int i = 0; i < 81; i ++)
if(board[i / 9][i % 9] == '.'){
assert(dfs(board, i, row, col, block));
return;
}
}
private:
bool dfs(vector<vector<char>>& board, int pos,
vector<vector<bool>>& row, vector<vector<bool>>& col,
vector<vector<bool>>& block){
if(pos == 81)
return true;
int next = pos + 1;
for(; next < 81; next ++)
if(board[next / 9][next % 9] == '.')
break;
int x = pos / 9, y = pos % 9;
for(int i = 1; i <= 9; i ++)
if(!row[x][i] && !col[y][i] && !block[x / 3 * 3 + y / 3][i]){
row[x][i] = true;
col[y][i] = true;
block[x / 3 * 3 + y / 3][i] = true;
board[x][y] = '0' + i;
if(dfs(board, next, row, col, block))
return true;
row[x][i] = false;
col[y][i] = false;
block[x / 3 * 3 + y / 3][i] = false;
board[x][y] = '.';
}
return false;
}
};
提交后的结果如下:
日积月累,与君共进,增增小结,未完待续。