åę ęÆę
å¦ęęØč§å¾čæäøŖē¬č®°åƹęØęęåø®å©ļ¼ēåØDēå„ē čæä¹å¤åēč¾č¦äøļ¼čÆ·åę ęÆęäøäøļ¼Dēå„ęęæäøå°½ļ¼š
ęäŗęčµēęååøęåÆä»„å 个儽åļ¼ę¬¢čæå ³ę³ØD ēå„ēå¾®äæ”å ¬ä¼å·ļ¼čæę ·å°±åÆä»„éčæå ¬ä¼å·ēåå¤ē“ę„ē»ęåäæ”ęÆć
å
¬ä¼å·ē微俔å·ęÆ: jikerizhi ćå äøŗä¼ęåØē„ēåå ļ¼ęę¶å¾ēå č½½äøåŗę„ć å¦ęå¾ēå č½½äøåŗę„åÆä»„ē“ę„éčæę瓢微俔å·ę„ę„ę¾ęēå
¬ä¼å·ć |
37. č§£ę°ē¬
ē¼åäøäøŖēØåŗļ¼éčæå”«å ē©ŗę ¼ę„č§£å³ę°ē¬é®é¢ć
ę°ē¬ēč§£ę³é éµå¾Ŗå¦äøč§åļ¼
-
ę°å
1-9
åØęÆäøč”åŖč½åŗē°äøę¬”ć -
ę°å
1-9
åØęÆäøååŖč½åŗē°äøę¬”ć -
ę°å
1-9
åØęÆäøäøŖä»„ē²å®ēŗæåéē3x3
宫å åŖč½åŗē°äøę¬”ćļ¼čÆ·åč示ä¾å¾ļ¼
ę°ē¬éØåē©ŗę ¼å
已唫å
„äŗę°åļ¼ē©ŗē½ę ¼ēØ .
蔨示ć
ē¤ŗä¾ 1ļ¼


č¾å „ļ¼board = [ ["5","3",".",".","7",".",".",".","."], ["6",".",".","1","9","5",".",".","."], [".","9","8",".",".",".",".","6","."], ["8",".",".",".","6",".",".",".","3"], ["4",".",".","8",".","3",".",".","1"], ["7",".",".",".","2",".",".",".","6"], [".","6",".",".",".",".","2","8","."], [".",".",".","4","1","9",".",".","5"], [".",".",".",".","8",".",".","7","9"]] č¾åŗļ¼[ ["5","3","4","6","7","8","9","1","2"], ["6","7","2","1","9","5","3","4","8"], ["1","9","8","3","4","2","5","6","7"], ["8","5","9","7","6","1","4","2","3"], ["4","2","6","8","5","3","7","9","1"], ["7","1","3","9","2","4","8","5","6"], ["9","6","1","5","3","7","2","8","4"], ["2","8","7","4","1","9","6","3","5"], ["3","4","5","2","8","6","1","7","9"]] č§£éļ¼č¾å „ēę°ē¬å¦äøå¾ę示ļ¼åÆäøęęēč§£å³ę¹ę”å¦äøę示ļ¼
ę示ļ¼
-
board.length == 9
-
board[i].length == 9
-
board[i][j]
ęÆäøä½ę°åęč.
-
é¢ē®ę°ę® äæčÆ č¾å „ę°ē¬ä» ęäøäøŖč§£
ęč·Æåę
čæéé¢ē¹å«éč¦å ³ę³Øēē¹ęÆļ¼åŖč¦ę¾å°äøäøŖč§£å°±åÆä»„äŗļ¼äøéč¦ę±å ØéØč§£ćę仄ļ¼éč¦éē¹ęčēęÆļ¼å¦ä½åØę¾å°ē¬¬äøäøŖč§£ę¶ļ¼å°±ē«å³åę¢ęē“¢ć
å°čÆē»äøäøéå½ę ļ¼
ä½čæē®ēé¼ļ¼ä½æēØ 1~9
ēęÆē¹ä½ę„蔨示ęÆå¦å·²ē»ååØęäøŖę°åć
使ēØå¼ęčäøęÆä½æēØęļ¼ęåŖč½ēØäŗåꬔę č®°ļ¼ä» 0
å¼å§ę č®°ļ¼ę仄ļ¼ę 论ęÆå¼ęčæęÆęļ¼č·äøäøŖ 1
ēøč®”ē®ļ¼é½åÆä»„ę 1`äæēäøę„ļ¼ćčå¼ęēä¼ē¹ęÆļ¼åØéę©åę¤éę¶ļ¼åÆä»„使ēØēøåēęä½ļ¼åå§ęÆē¹ęÆ `0
ļ¼å¼ęåęÆ 1
ļ¼åå¼ęåęÆ 0
ļ¼ć
č”ååēøę rows | columns | boxes
åļ¼čæęÆ 0
ēęÆē¹ä½ļ¼å°±ęÆéč¦å¾
唫å
ēå¼ćęæé¢ē®å®ä¾ę„äø¾ä¾ļ¼
84 1010100 rows[0] 128 10000000 column[2] 436 110110100 box[0][0] å·¦äøč§ē9äøŖę¹ę ¼ 500 111110100 rows[0] | columns[2] | boxes[0][0] = or -501 11111111111111111111111000001011 ~or 11 1011 ~or & 0x1FF = mask 1 1 mask & (-mask) ååŗęåäøä½ 1 ēäøę mask &= (mask - 1) ę¼čæå°äøäøę„

-
äøå·
-
äŗå·
-
äŗå·ļ¼å¼å „ę„čæļ¼
-
äøå·
-
åå·
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/**
* * @author Dēå„ Ā· https://www.diguage.com
* * @since 2020-03-25 09:34
*/
public void solveSudoku(char[][] board) {
backtrack(board, 0);
}
/**
* Runtime: 17 ms, faster than 35.23% of Java online submissions for Sudoku Solver.
* Memory Usage: 37 MB, less than 21.05% of Java online submissions for Sudoku Solver.
*/
private boolean backtrack(char[][] board, int step) {
int len = board.length;
if (step == len * len) {
return true;
}
int y = step / len;
int x = step % len;
for (int i = y; i < len; i++) {
for (int j = x; j < len; j++) {
if (board[i][j] != '.') {
return backtrack(board, step + 1);
}
for (char c = '1'; c <= '9'; c++) {
if (!isValid(board, i, j, c)) {
continue;
}
board[i][j] = c;
System.out.printf("y=%d,x=%d, num=%s, step=%d %n",
y, x, c, step);
Printers.printMatrix(board);
if (backtrack(board, step + 1)) {
return true;
}
board[i][j] = '.';
}
return false;
}
}
return false;
}
private boolean isValid(char[][] board, int y, int x, char c) {
for (int i = 0; i < 9; i++) {
if (board[(y / 3) * 3 + i / 3][(x / 3) * 3 + i % 3] == c
|| board[y][i] == c
|| board[i][x] == c) {
return false;
}
}
return true;
}
/**
* Copy From
*/
private boolean backtrackXY(char[][] board, int y, int x) {
int len = board.length;
if (x == len) {
return backtrackXY(board, y + 1, 0);
}
if (y == len) {
return true;
}
for (int i = y; i < len; i++) {
for (int j = x; j < len; j++) {
if (board[i][j] != '.') {
return backtrackXY(board, i, j + 1);
}
for (char c = '1'; c <= '9'; c++) {
if (!isValid(board, i, j, c)) {
continue;
}
board[i][j] = c;
System.out.printf("y=%d,x=%d, num=%s %n", i, j, c);
Printers.printMatrix(board);
if (backtrackXY(board, i, j + 1)) {
return true;
}
board[i][j] = '.';
}
return false;
}
}
return false;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/**
* * @author Dēå„ Ā· https://www.diguage.com
* * @since 2024-09-11 10:59:08
*/
public void solveSudoku(char[][] board) {
backtracking(board);
}
private boolean backtracking(char[][] board) {
for (int r = 0; r < board.length; r++) {
for (int c = 0; c < board[r].length; c++) {
if (board[r][c] != '.') {
continue;
}
// ę ¹ę®éå¶ę”ä»¶ļ¼ēéåŗåÆéå符ļ¼å¦åéå¤å¤ę
char[] chars = selectChars(board, r, c);
for (char sc : chars) {
board[r][c] = sc;
printMatrix(board);
if (backtracking(board)) {
return true;
}
board[r][c] = '.';
}
return false;
}
}
return true;
}
private char[] selectChars(char[][] board, int row, int column) {
char[] chars = new char[9];
int length = 9;
for (int i = 0; i < chars.length; i++) {
chars[i] = (char) ('1' + i);
}
for (int i = 0; i < board.length; i++) {
char c = board[i][column];
if (c != '.' && chars[c - '1'] != '.') {
chars[c - '1'] = '.';
length--;
if (length == 0) {
return new char[0];
}
}
}
for (int i = 0; i < board[row].length; i++) {
char c = board[row][i];
if (c != '.' && chars[c - '1'] != '.') {
chars[c - '1'] = '.';
length--;
if (length == 0) {
return new char[0];
}
}
}
row = (row / 3) * 3;
column = (column / 3) * 3;
for (int i = row; i < row + 3; i++) {
for (int j = column; j < column + 3; j++) {
char c = board[i][j];
if (c != '.' && chars[c - '1'] != '.') {
chars[c - '1'] = '.';
length--;
if (length == 0) {
return new char[0];
}
}
}
}
char[] result = new char[length];
for (int i = chars.length - 1; i >= 0; i--) {
if (chars[i] != '.') {
result[--length] = chars[i];
}
}
return result;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/**
* * @author Dēå„ Ā· https://www.diguage.com
* * @since 2024-09-11 10:59:08
*/
public void solveSudoku(char[][] board) {
backtracking(board, 0);
}
private boolean backtracking(char[][] board, int step) {
int row = step / board.length;
int column = step % board.length;
for (int r = row; r < board.length; r++) {
for (int c = column; c < board[r].length; c++) {
if (board[r][c] != '.') {
return backtracking(board, step + 1);
}
// ę ¹ę®éå¶ę”ä»¶ļ¼ēéåŗåÆéå符ļ¼å¦åéå¤å¤ę
char[] chars = selectChars(board, r, c);
for (char sc : chars) {
board[r][c] = sc;
printMatrix(board);
if (backtracking(board, step + 1)) {
return true;
}
board[r][c] = '.';
}
return false;
}
}
return true;
}
private char[] selectChars(char[][] board, int row, int column) {
char[] chars = new char[9];
int length = 9;
for (int i = 0; i < chars.length; i++) {
chars[i] = (char) ('1' + i);
}
for (int i = 0; i < board.length; i++) {
char c = board[i][column];
if (c != '.' && chars[c - '1'] != '.') {
chars[c - '1'] = '.';
length--;
if (length == 0) {
return new char[0];
}
}
}
for (int i = 0; i < board[row].length; i++) {
char c = board[row][i];
if (c != '.' && chars[c - '1'] != '.') {
chars[c - '1'] = '.';
length--;
if (length == 0) {
return new char[0];
}
}
}
row = (row / 3) * 3;
column = (column / 3) * 3;
for (int i = row; i < row + 3; i++) {
for (int j = column; j < column + 3; j++) {
char c = board[i][j];
if (c != '.' && chars[c - '1'] != '.') {
chars[c - '1'] = '.';
length--;
if (length == 0) {
return new char[0];
}
}
}
}
char[] result = new char[length];
for (int i = chars.length - 1; i >= 0; i--) {
if (chars[i] != '.') {
result[--length] = chars[i];
}
}
return result;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/**
* * @author Dēå„ Ā· https://www.diguage.com
* * @since 2024-09-11 10:59:08
*/
public void solveSudoku(char[][] board) {
// 使ēØęÆē¹ä½ę„ę 注已ē»ååØåŖäŗå符
int[] rows = new int[9];
int[] columns = new int[9];
int[][] boxes = new int[3][3];
List<int[]> positions = new ArrayList<>();
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board.length; j++) {
char c = board[i][j];
if (c == '.') {
// č®°å½éč¦å”«å
ēä½ē½®
positions.add(new int[]{i, j});
} else {
int num = c - '0' - 1;
flip(rows, columns, boxes, i, j, num);
}
}
}
// 使ēØåęŗÆå°čÆå”«å
backtrack(board, rows, columns, boxes, positions, 0);
}
private boolean backtrack(char[][] board,
int[] rows, int[] columns, int[][] boxes,
List<int[]> positions, int index) {
if (positions.size() == index) {
return true;
}
int[] pos = positions.get(index);
int r = pos[0];
int c = pos[1];
// ęå¼čæäŗč¾åŗļ¼å°±č¶
ę¶ćå
³éļ¼å°±č½č¶
čæ 90%
// System.out.printf("%5d %33s\n", rows[r], Integer.toBinaryString(rows[r]));
// System.out.printf("%5d %33s\n", columns[c], Integer.toBinaryString(columns[c]));
// System.out.printf("%5d %33s\n", boxes[r / 3][c / 3], Integer.toBinaryString(boxes[r / 3][c / 3]));
int orNum = rows[r] | columns[c] | boxes[r / 3][c / 3];
// System.out.printf("%5d %33s\n", orNum, Integer.toBinaryString(orNum));
int negNum = ~orNum;
// System.out.printf("%5d %33s\n", negNum, Integer.toBinaryString(negNum));
int mask = negNum & 0x1FF;
// System.out.printf("%5d %33s\n", mask, Integer.toBinaryString(mask));
for (; mask != 0; mask &= (mask - 1)) {
int digitMask = mask & (-mask);
// System.out.printf("%5d %33s\n", digitMask, Integer.toBinaryString(digitMask));
// System.out.printf("%5d %33s\n", digitMask - 1, Integer.toBinaryString(digitMask - 1));
int num = Integer.bitCount(digitMask - 1);
// System.out.println(num);
flip(rows, columns, boxes, r, c, num);
board[r][c] = (char) (num + '0' + 1);
boolean result = backtrack(board, rows, columns, boxes, positions, index + 1);
if (result) {
return true;
}
flip(rows, columns, boxes, r, c, num);
}
return false;
}
private void flip(int[] rows, int[] columns, int[][] boxes,
int i, int j, int num) {
int digit = 1 << num;
// čæé使ēØå¼ęčäøęÆä½æēØęļ¼ęåŖč½ēØäŗåꬔę č®°ć
// čå¼ęēä¼ē¹ęÆļ¼åØéę©åę¤éę¶ļ¼åÆä»„使ēØēøåēęä½ć
rows[i] ^= digit;
columns[j] ^= digit;
boxes[i / 3][j / 3] ^= digit;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/**
* * @author Dēå„ Ā· https://www.diguage.com
* * @since 2025-06-21 22:01:54
*/
public void solveSudoku(char[][] board) {
int length = board.length;
boolean[][] rows = new boolean[length][length];
boolean[][] cols = new boolean[length][length];
boolean[][][] blocks = new boolean[3][3][length];
for (int r = 0; r < length; r++) {
for (int c = 0; c < length; c++) {
char ac = board[r][c];
if (ac == '.') {
continue;
}
int idx = ac - '1';
rows[r][idx] = true;
cols[c][idx] = true;
blocks[r / 3][c / 3][idx] = true;
}
}
backtrack(board, rows, cols, blocks, 0);
}
private boolean backtrack(char[][] board, boolean[][] rows, boolean[][] cols,
boolean[][][] blocks, int index) {
if (index == board.length * board.length) {
return true;
}
int row = index / 9;
int col = index % 9;
if (board[row][col] != '.') {
return backtrack(board, rows, cols, blocks, index + 1);
}
for (int i = 0; i < 9; i++) {
if (rows[row][i] || cols[col][i] || blocks[row / 3][col / 3][i]) {
continue;
}
rows[row][i] = true;
cols[col][i] = true;
blocks[row / 3][col / 3][i] = true;
board[row][col] = (char) (i + '1');
if (backtrack(board, rows, cols, blocks, index + 1)) {
return true;
}
board[row][col] = '.';
rows[row][i] = false;
cols[col][i] = false;
blocks[row / 3][col / 3][i] = false;
}
return false;
}