Skip to content

Commit 4211da8

Browse files
authored
feat: add weekly contest 465 (#4680)
1 parent f361e24 commit 4211da8

File tree

18 files changed

+1289
-567
lines changed

18 files changed

+1289
-567
lines changed

solution/0000-0099/0037.Sudoku Solver/README.md

Lines changed: 67 additions & 189 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,9 @@ tags:
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-
166162
class Solution {
167163
public:
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
251247
public 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
387291
class 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

Comments
 (0)