1+ // 解数独
2+
3+
4+ /*
5+ 回溯:
6+ 1、本题中棋盘的每一个位置都要放一个数字,并检查数字是否合法,解数独的树形结构要比N皇后更宽更深。
7+ 2、为什么递归函数的返回值需要是bool类型?
8+ 因为解数独找到一个符合的条件(就在树的叶子节点上)立刻就返回,相当于找从根节点到叶子节点一条唯一路径,所以需要使用bool返回值
9+ 3、本题在原二维数组上操作,因此不需要增加额外的数据结构
10+ 4、本题递归不用终止条件,解数独是要遍历整个树形结构寻找可能的叶子节点就立刻返回
11+ 5、本题需要 二维递归,也就是两个for循环嵌套着递归
12+ 一个for循环遍历棋盘的行,一个for循环遍历棋盘的列,一行一列确定下来之后,递归遍历这个位置放9个数字的可能性!
13+ */
14+ class Solution {
15+ public void solveSudoku (char [][] board ) {
16+ backtrack (board );
17+ }
18+
19+ private boolean backtrack (char [][] board ) {
20+ for (int row = 0 ; row < 9 ; row ++) {
21+ for (int col = 0 ; col < 9 ; col ++) {
22+ if (board [row ][col ] != '.' ) {
23+ continue ;
24+ }
25+ for (char val = '1' ; val <= '9' ; val ++) {
26+ if (isValid (row , col , val , board )) {
27+ board [row ][col ] = val ;
28+ if (backtrack (board )) {
29+ return true ;
30+ }
31+ board [row ][col ] = '.' ;
32+ }
33+ }
34+ // 9个数都试完了,都不行,那么就返回false
35+ return false ;
36+ }
37+ }
38+ // 遍历完没有返回false,说明找到了合适棋盘位置
39+ return true ;
40+ }
41+
42+ private boolean isValid (int row , int col , char val , char [][] board ) {
43+ // 判断同一行是否有重复的数
44+ for (int i = 0 ; i < 9 ; i ++) {
45+ if (board [row ][i ] == val ) {
46+ return false ;
47+ }
48+ }
49+ // 判断同一列是否有重复的数
50+ for (int j = 0 ; j < 9 ; j ++) {
51+ if (board [j ][col ] == val ) {
52+ return false ;
53+ }
54+ }
55+ // 判断九宫格是否有重复的数
56+ int startRow = (row / 3 ) * 3 ;
57+ int startCol = (col / 3 ) * 3 ;
58+ for (int i = startRow ; i < startRow + 3 ; i ++) {
59+ for (int j = startCol ; j < startCol + 3 ; j ++) {
60+ if (board [i ][j ] == val ) {
61+ return false ;
62+ }
63+ }
64+ }
65+ return true ;
66+ }
67+ }
0 commit comments