本周题目难度级别'Hard',好久没做Hard级别的题目了,这周题目也很典型。。。
题目:给你一个合法且有解的数独,空白处用'.'代替,求解数独(可以认为只有唯一解)
题目比较典型,使用backtracking(回溯算法)
,用在这道题上的解释就是一个一个试,直到试正确为止,下面用代码来看一下,和上周一样,从最后一个函数solveSudoku
开始看:
//找到下一个空白的位置,即'.'
bool GetNextDot(char** board, int *row, int *col) {
//遍历找'.'的行数和列数,比较简单,不说了
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if (board[i][j] == '.') {
*row = i;
*col = j;
return 1;
}
}
}
return 0;
}
//验证num这个数字是否合法
bool checkNum(char** board, int* row, int* col, char num) {
//检查行,看是否有num这个数
for (int i = 0; i < 9; i++) {
if (board[*row][i] == num) {
return 0;
}
}
//检查列,看是否有num这个数
for (int i = 0; i < 9; i++) {
if (board[i][*col] == num) {
return 0;
}
}
//检查num所在的九宫格,看是否有num这个数
int x = *row / 3;
int y = *col / 3;
for (int i = x * 3; i < x * 3 + 3; i++) {
for (int j = y * 3; j < y * 3 + 3; j++) {
if (board[i][j] == num) {
return 0;
}
}
}
return 1;
}
//求解数独
bool solveSudokuTool(char **board) {
//开辟空间,并初始化行数和列数
int *row = malloc(sizeof(int));
int *col = malloc(sizeof(int));
*row = 0;
*col = 0;
//寻找一个空白的位置,即'.'的行列数
if (!GetNextDot(board, row, col)) return 1;
//从1〜9一个一个数字代入试
for (char num = '1'; num <= '9'; num++) {
//检查代入试的数字是否合法
if (checkNum(board, row, col, num)) {
//合法就将数字填入
board[*row][*col] = num;
//将填入数字后的数独继续迭代
if (solveSudokuTool(board)) {
return 1;
}
//如果结果是错的,就将这个数重新置为空白,即'.'
board[*row][*col] = '.';
}
}
return 0;
}
void solveSudoku(char** board, int boardRowSize, int boardColSize) {
//调用求解
solveSudokuTool(board);
}
效率一般,关键是要掌握回溯算法。发现了个规律,越是难度级别低的算法题,我越是有兴趣提高效率,越是难的我对自己的要求越低,哈哈。。。