回溯进阶(二):以解数独来深入了解映射
题目:
链接:
https://leetcode.cn/problems/sudoku-solver/
题解:
class Solution {public int[][] rows=new int[9][9];public int[][] cols=new int[9][9];public int[][][] grids=new int[3][3][9];public void solveSudoku(char[][] board) {//这一步是为了初始化行列宫。//为什么d要减去'1'而不是'0',为了不越界(0-8而不是1-9)for(int i=0;i<9;i++){for(int j=0;j<9;j++){if(board[i][j]!='.'){int d=board[i][j]-'1';rows[i][d]=1;cols[j][d]=1;grids[i/3][j/3][d]=1;}}}traceBack(0,board);}public boolean traceBack(int pos,char[][] board){if(pos==81) return true;int i=pos/9;int j=pos%9;if(board[i][j]!='.') return traceBack(pos+1,board);//为什么要遍历从0到8?//这是可能存在的状态,在回溯思想中,提到了遍历是为了遍历所有可能转移的状态for(int d=0;d<9;d++){//这个判断表示:行,列,宫中若存在该数字,则为d为无效的,直接剪枝即可。if(rows[i][d]!=0 || cols[j][d]!=0 || grids[i/3][j/3][d]!=0) continue;rows[i][d]=1;cols[j][d]=1;grids[i/3][j/3][d]=1;board[i][j]=(char)(d+'1');if(traceBack(pos+1,board)) return true;rows[i][d]=0;cols[j][d]=0;grids[i/3][j/3][d]=0;board[i][j]='.';}return false;}
}
答疑点:
1.rows为什么要开辟9*9的空间?
答:第一个9代表9行,第二个9代表有这个位置有9种可能的结果(要搭配cols来看)
cols的第一个9代表9行,第二个9代表这个位置有9种可能的结果;
grids是339。前两个3*3表示3行3列构成一个宫,9表示这个位置有9种可能的结果
2.pos是什么意思?
答:是一种映射关系,将9*9的棋盘映射成一维数组(从0到80),这样行,列,宫就可以用pos来表示了:
- 行:i=pos/9;
- 列:j=pos%9;
- 宫:i/3,j/3;
收获:
映射真的好用,这个pos直接将二维变成一维表示,yyds。很多复杂的回溯题,都是靠映射来化繁为简的。
在保证回溯结构不变的情况下,回溯问题不会很难,顺着回溯思路走即可,若不会回溯思路,可看这篇文章:
https://blog.csdn.net/2302_80396926/article/details/147764527?spm=1001.2014.3001.5501