这是我参与11月更文挑战的第29天,活动详情查看:2021最后一次更文挑战
一、数独
就是一个9*9的宫格,数字1-9每行每列只能出现一次,把九宫格分成3*3的小方格,每个3*3的方格中也只能出现一次。我们可以通过填充空格的方式解开,还是一样的可以通过递归和回溯方法,只不过判断条件变成横竖的1-9和3个宫格中的1-9的数字只能出现一次。
题目:解数独
var solveSudoku = function(board) {
for(let i = 0;i<9;i++) {
for(let j = 0;j<9;j++) {
if(board[i][j] !== '.') continue;
//放一个数字试试
for(let k = 1;k<=9;k++) {
if(isValid(board,i,j,k.toString())) {
//可以放
board[i][j] = k.toString();
if(solveSudoku(board)) return true;
//回溯
board[i][j] = '.';
}
}
return false;
}
}
return true;
}
//验证数字能不能放
function isValid(board,row,col,k) {
const x = Math.floor(row/3) * 3;
const y = Math.floor(col/3) * 3;
for(let i = 0;i<9;i++) {
if(board[row][i] === k || board[i][col] === k) {
return false;
}
}
//小方块
for(let i = 0;i<3;i++) {
for(let j = 0;j<3;j++) {
if(board[x+i][y+j] === k) {
return false
}
}
}
return true;
}
思路:
- 需要在一个空格中放一个类似棋子一样的试一下,不行就换一不,算法之间都是相互有关系的,比如DFS数独就类似DFS深度优先搜索有点相似,不是空格就是数字,是空格就是用小数点代替。
- 然后随便用一个数字在空格中代替,再到横竖和当前在的小方格内有没有数字和他一样,因为只能出现一次,这个可以作为终止条件。
- 遍历9行和9列这样就是一个9*9的小方格,board就是一个二维数组,先判断一个终止条件,如果是数字不是空格就直接终止执行下一个,如果是小数点是空格,就要放一个1-9之间的数字,判断是否可以放单独做校验传入行、列、尝试的数字
- 校验是否能放:当前的行每个数字是否有这个数字,当前列是否有这个数字,还要3*3的小宫格内是否有这个数字,这个就要定义x代表行和y代表列来拿到位置,x是当前位置除以3再取整,最后判断这个小方格里是否有数字等于当前数字。
- 如果这个数字能放就要做递归,如果不能放就做回溯。
数独这道题主要就是递归和回溯比较麻烦,在做难题的时候一定要想好条件,把所有终止条件列好,比如这题就是三个终止条件:1、每行不能有重复的数字;2、每列不能有重复的数字;3、单独的3*3的小方格内不能有重复的数字。,然后再做验证方面的功能,最后再递归回溯检查一下没问题就可以了。