6868
6969### 方法一:回溯
7070
71- 我们用数组 ` row ` 、 ` col ` 、 ` box ` 分别记录每一行、每一列、每个 3x3 宫格中数字是否出现过。如果数字 ` i ` 在第 ` r ` 行、第 ` c ` 列、第 ` b ` 个 3x3 宫格中出现过,那么 ` row[r][i] ` 、 ` col[c][i] ` 、 ` box[b][i] ` 都为 ` true ` 。
71+ 我们用数组 $\textit{ row}$, $\textit{ col}$, $\textit{ box}$ 分别记录每一行、每一列、每个 3x3 宫格中数字是否出现过。如果数字 $i$ 在第 $r$ 行、第 $c$ 列、第 $b$ 个 3x3 宫格中出现过,那么 $\text{ row[ r] [ i ] }$, $\text{ col[ c] [ i ] }$, $\text{ box[ b] [ i ] }$ 都为 $ true$ 。
7272
73- 我们遍历 ` board ` 的每一个空格,枚举它可以填入的数字 ` v ` ,如果 ` v ` 在当前行、当前列、当前 3x3 宫格中没有出现过,那么我们就可以尝试填入数字 ` v ` ,并继续搜索下一个空格。如果搜索到最后,所有空格填充完毕,那么就说明找到了一个可行解。
74-
75- 时间复杂度 $O(9^{81})$,空间复杂度 $O(9^2)$。
73+ 我们遍历 $\textit{board}$ 中的每一个空格,枚举它可以填入的数字 $v$,如果 $v$ 在当前行、当前列、当前 3x3 宫格中没有出现过,那么我们就可以尝试填入数字 $v$,并继续搜索下一个空格。如果搜索到最后,所有空格填充完毕,那么就说明找到了一个可行解。
7674
7775<!-- tabs:start -->
7876
@@ -161,16 +159,14 @@ class Solution {
161159#### C++
162160
163161``` cpp
164- using pii = pair<int , int >;
165-
166162class Solution {
167163public:
168164 void solveSudoku(vector<vector<char >>& board) {
169165 bool row[ 9] [ 9 ] = {false};
170166 bool col[ 9] [ 9 ] = {false};
171167 bool block[ 3] [ 3 ] [ 9] = {false};
172168 bool ok = false;
173- vector<pii > t;
169+ vector<pair<int, int> > t;
174170 for (int i = 0; i < 9; ++i) {
175171 for (int j = 0; j < 9; ++j) {
176172 if (board[ i] [ j ] == '.') {
@@ -181,7 +177,7 @@ public:
181177 }
182178 }
183179 }
184- function<void(int k)> dfs = [ &] (int k) {
180+ auto dfs = [ &] (this auto&& dfs, int k) -> void {
185181 if (k == t.size()) {
186182 ok = true;
187183 return;
@@ -250,133 +246,41 @@ func solveSudoku(board [][]byte) {
250246``` cs
251247public class Solution {
252248 public void SolveSudoku (char [][] board ) {
253- this .board = new ushort ?[9 ,9 ];
254- for (var i = 0 ; i < 9 ; ++ i )
255- {
256- for (var j = 0 ; j < 9 ; ++ j )
257- {
258- if (board [i ][j ] != '.' )
259- {
260- this .board [i , j ] = (ushort ) (1 << (board [i ][j ] - '0' - 1 ));
261- }
262- }
263- }
249+ bool [,] row = new bool [9 , 9 ];
250+ bool [,] col = new bool [9 , 9 ];
251+ bool [,,] block = new bool [3 , 3 , 9 ];
252+ bool ok = false ;
253+ var t = new List <(int , int )>();
264254
265- if (SolveSudoku (0 , 0 ))
266- {
267- for (var i = 0 ; i < 9 ; ++ i )
268- {
269- for (var j = 0 ; j < 9 ; ++ j )
270- {
271- if (board [i ][j ] == '.' )
272- {
273- board [i ][j ] = '0' ;
274- while (this .board [i , j ].Value != 0 )
275- {
276- board [i ][j ] = (char )(board [i ][j ] + 1 );
277- this .board [i , j ] >>= 1 ;
278- }
279- }
255+ for (int i = 0 ; i < 9 ; ++ i ) {
256+ for (int j = 0 ; j < 9 ; ++ j ) {
257+ if (board [i ][j ] == '.' ) {
258+ t .Add ((i , j ));
259+ } else {
260+ int v = board [i ][j ] - '1' ;
261+ row [i , v ] = col [j , v ] = block [i / 3 , j / 3 , v ] = true ;
280262 }
281263 }
282264 }
283- }
284265
285- private ushort ?[,] board ;
286-
287- private bool ValidateHorizontalRule (int row )
288- {
289- ushort temp = 0 ;
290- for (var i = 0 ; i < 9 ; ++ i )
291- {
292- if (board [row , i ].HasValue )
293- {
294- if ((temp | board [row , i ].Value ) == temp )
295- {
296- return false ;
297- }
298- temp |= board [row , i ].Value ;
299- }
300- }
301- return true ;
302- }
303-
304- private bool ValidateVerticalRule (int column )
305- {
306- ushort temp = 0 ;
307- for (var i = 0 ; i < 9 ; ++ i )
308- {
309- if (board [i , column ].HasValue )
310- {
311- if ((temp | board [i , column ].Value ) == temp )
312- {
313- return false ;
314- }
315- temp |= board [i , column ].Value ;
266+ void Dfs (int k ) {
267+ if (k == t .Count ) {
268+ ok = true ;
269+ return ;
316270 }
317- }
318- return true ;
319- }
320-
321- private bool ValidateBlockRule (int row , int column )
322- {
323- var startRow = row / 3 * 3 ;
324- var startColumn = column / 3 * 3 ;
325- ushort temp = 0 ;
326- for (var i = startRow ; i < startRow + 3 ; ++ i )
327- {
328- for (var j = startColumn ; j < startColumn + 3 ; ++ j )
329- {
330- if (board [i , j ].HasValue )
331- {
332- if ((temp | board [i , j ].Value ) == temp )
333- {
334- return false ;
335- }
336- temp |= board [i , j ].Value ;
271+ var (i , j ) = t [k ];
272+ for (int v = 0 ; v < 9 ; ++ v ) {
273+ if (! row [i , v ] && ! col [j , v ] && ! block [i / 3 , j / 3 , v ]) {
274+ row [i , v ] = col [j , v ] = block [i / 3 , j / 3 , v ] = true ;
275+ board [i ][j ] = (char )(v + '1' );
276+ Dfs (k + 1 );
277+ if (ok ) return ;
278+ row [i , v ] = col [j , v ] = block [i / 3 , j / 3 , v ] = false ;
337279 }
338280 }
339281 }
340- return true ;
341- }
342-
343- private bool SolveSudoku (int i , int j )
344- {
345- while (true )
346- {
347- if (j == 9 )
348- {
349- ++ i ;
350- j = 0 ;
351- }
352- if (i == 9 )
353- {
354- return true ;
355- }
356- if (board [i , j ].HasValue )
357- {
358- ++ j ;
359- }
360- else
361- {
362- break ;
363- }
364- }
365282
366- ushort stop = 1 << 9 ;
367- for (ushort t = 1 ; t != stop ; t <<= 1 )
368- {
369- board [i , j ] = t ;
370- if (ValidateHorizontalRule (i ) && ValidateVerticalRule (j ) && ValidateBlockRule (i , j ))
371- {
372- if (SolveSudoku (i , j + 1 ))
373- {
374- return true ;
375- }
376- }
377- }
378- board [i , j ] = null ;
379- return false ;
283+ Dfs (0 );
380284 }
381285}
382286```
@@ -386,78 +290,52 @@ public class Solution {
386290``` php
387291class Solution {
388292 /**
389- * @param string [][] $board
390- * @return bool
293+ * @param String [][] $board
294+ * @return NULL
391295 */
392-
393- public function solveSudoku(& $board) {
394- if (isSolved($board)) {
395- return true;
396- }
397-
398- $emptyCell = findEmptyCell($board);
399- $row = $emptyCell[0];
400- $col = $emptyCell[1];
401-
402- for ($num = 1; $num <= 9; $num++) {
403- if (isValid($board, $row, $col, $num)) {
404- $board[$row][$col] = (string) $num;
405- if ($this->solveSudoku($board)) {
406- return true;
296+ function solveSudoku(& $board) {
297+ $row = array_fill(0, 9, array_fill(0, 9, false));
298+ $col = array_fill(0, 9, array_fill(0, 9, false));
299+ $block = array_fill(0, 3, array_fill(0, 3, array_fill(0, 9, false)));
300+ $ok = false;
301+ $t = [];
302+
303+ for ($i = 0; $i < 9; ++$i) {
304+ for ($j = 0; $j < 9; ++$j) {
305+ if ($board[$i][$j] === '.') {
306+ $t[] = [$i, $j];
307+ } else {
308+ $v = ord($board[$i][$j]) - ord('1');
309+ $row[$i][$v] = true;
310+ $col[$j][$v] = true;
311+ $block[intval($i / 3)][intval($j / 3)][$v] = true;
407312 }
408- $board[$row][$col] = '.';
409313 }
410314 }
411- return false;
412- }
413- }
414-
415- function isSolved($board) {
416- foreach ($board as $row) {
417- if (in_array('.', $row)) {
418- return false;
419- }
420- }
421- return true;
422- }
423315
424- function findEmptyCell($board) {
425- for ($row = 0; $row < 9; $row++) {
426- for ($col = 0; $col < 9; $col++) {
427- if ($board[$row][$col] === '.') {
428- return [$row, $col];
316+ $dfs = function ($k) use (& $dfs, & $board, & $row, & $col, & $block, & $ok, & $t) {
317+ if ($k === count($t)) {
318+ $ok = true;
319+ return;
429320 }
430- }
431- }
432-
433- return null;
434- }
435-
436- function isValid($board, $row, $col, $num) {
437- for ($i = 0; $i < 9; $i++) {
438- if ($board[$row][$i] == $num) {
439- return false;
440- }
441- }
442-
443- for ($i = 0; $i < 9; $i++) {
444- if ($board[$i][$col] == $num) {
445- return false;
446- }
447- }
448-
449- $startRow = floor($row / 3) * 3;
450- $endCol = floor($col / 3) * 3;
451-
452- for ($i = 0; $i < 3; $i++) {
453- for ($j = 0; $j < 3; $j++) {
454- if ($board[$startRow + $i][$endCol + $j] == $num) {
455- return false;
321+ [$i, $j] = $t[$k];
322+ for ($v = 0; $v < 9; ++$v) {
323+ if (!$row[$i][$v] && !$col[$j][$v] && !$block[intval($i / 3)][intval($j / 3)][$v]) {
324+ $row[$i][$v] = $col[$j][$v] = $block[intval($i / 3)][intval($j / 3)][$v] = true;
325+ $board[$i][$j] = chr($v + ord('1'));
326+ $dfs($k + 1);
327+ if ($ok) {
328+ return;
329+ }
330+ $row[$i][$v] = $col[$j][$v] = $block[intval($i / 3)][intval($j / 3)][
331+ $v
332+ ] = false;
333+ }
456334 }
457- }
458- }
335+ };
459336
460- return true;
337+ $dfs(0);
338+ }
461339}
462340```
463341
0 commit comments