68
68
69
69
### 方法一:回溯
70
70
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$ 。
72
72
73
- 我们遍历 ` board ` 的每一个空格,枚举它可以填入的数字 ` v ` ,如果 ` v ` 在当前行、当前列、当前 3x3 宫格中没有出现过,那么我们就可以尝试填入数字 ` v ` ,并继续搜索下一个空格。如果搜索到最后,所有空格填充完毕,那么就说明找到了一个可行解。
74
-
75
- 时间复杂度 $O(9^{81})$,空间复杂度 $O(9^2)$。
73
+ 我们遍历 $\textit{board}$ 中的每一个空格,枚举它可以填入的数字 $v$,如果 $v$ 在当前行、当前列、当前 3x3 宫格中没有出现过,那么我们就可以尝试填入数字 $v$,并继续搜索下一个空格。如果搜索到最后,所有空格填充完毕,那么就说明找到了一个可行解。
76
74
77
75
<!-- tabs:start -->
78
76
@@ -161,16 +159,14 @@ class Solution {
161
159
#### C++
162
160
163
161
``` cpp
164
- using pii = pair<int , int >;
165
-
166
162
class Solution {
167
163
public:
168
164
void solveSudoku(vector<vector<char >>& board) {
169
165
bool row[ 9] [ 9 ] = {false};
170
166
bool col[ 9] [ 9 ] = {false};
171
167
bool block[ 3] [ 3 ] [ 9] = {false};
172
168
bool ok = false;
173
- vector<pii > t;
169
+ vector<pair<int, int> > t;
174
170
for (int i = 0; i < 9; ++i) {
175
171
for (int j = 0; j < 9; ++j) {
176
172
if (board[ i] [ j ] == '.') {
@@ -181,7 +177,7 @@ public:
181
177
}
182
178
}
183
179
}
184
- function<void(int k)> dfs = [ &] (int k) {
180
+ auto dfs = [ &] (this auto&& dfs, int k) -> void {
185
181
if (k == t.size()) {
186
182
ok = true;
187
183
return;
@@ -250,133 +246,41 @@ func solveSudoku(board [][]byte) {
250
246
``` cs
251
247
public class Solution {
252
248
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 )>();
264
254
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 ;
280
262
}
281
263
}
282
264
}
283
- }
284
265
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 ;
316
270
}
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 ;
337
279
}
338
280
}
339
281
}
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
- }
365
282
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 );
380
284
}
381
285
}
382
286
```
@@ -386,78 +290,52 @@ public class Solution {
386
290
``` php
387
291
class Solution {
388
292
/**
389
- * @param string [][] $board
390
- * @return bool
293
+ * @param String [][] $board
294
+ * @return NULL
391
295
*/
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;
407
312
}
408
- $board[$row][$col] = '.';
409
313
}
410
314
}
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
- }
423
315
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;
429
320
}
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
+ }
456
334
}
457
- }
458
- }
335
+ };
459
336
460
- return true;
337
+ $dfs(0);
338
+ }
461
339
}
462
340
```
463
341
0 commit comments