Skip to content

Commit 8d51415

Browse files
committed
Add Sudoku Solver using Backtracking algorithm- Implements depth-first backtracking to solve 9×9 Sudoku puzzles- Includes validation for rows, columns, and 3×3 subgrids- Provides clean, modular implementation with helper methods- Includes comprehensive unit tests for solvable and unsolvable cases- Time Complexity: O(9^(n²)) in worst case- Space Complexity: O(n²) for recursion stack
1 parent 9cc1af8 commit 8d51415

2 files changed

Lines changed: 258 additions & 227 deletions

File tree

src/main/java/com/thealgorithms/backtracking/SudokuSolver.java

Lines changed: 171 additions & 145 deletions
Original file line numberDiff line numberDiff line change
@@ -2,169 +2,195 @@
22

33
/**
44
* Sudoku Solver using Backtracking Algorithm
5-
*
6-
* This class solves a partially filled 9×9 Sudoku board by finding a valid arrangement
7-
* where every row, column, and 3×3 subgrid contains digits 1-9 exactly once.
8-
*
5+
*
6+
* This class solves a partially filled 9×9 Sudoku board by finding a valid
7+
* arrangement where every row, column, and 3×3 subgrid contains digits 1-9
8+
* exactly once.
9+
*
10+
* Algorithm References:
11+
* - Backtracking: https://en.wikipedia.org/wiki/Backtracking
12+
* - Sudoku: https://en.wikipedia.org/wiki/Sudoku
13+
*
914
* Time Complexity: O(9^(n*n)) in worst case, where n=9
1015
* Space Complexity: O(n*n) for recursion stack
11-
*
16+
*
1217
* @author TheAlgorithms
1318
*/
1419
public class SudokuSolver {
1520

16-
private static final int SIZE = 9;
17-
private static final int SUBGRID_SIZE = 3;
18-
private static final int EMPTY = 0;
19-
20-
/**
21-
* Solves the given Sudoku board using backtracking.
22-
* Modifies the board in-place.
23-
*
24-
* @param board 9×9 2D array representing the Sudoku board (0 = empty cell)
25-
* @return true if a valid solution exists, false otherwise
26-
*/
27-
public static boolean solveSudoku(int[][] board) {
28-
for (int row = 0; row < SIZE; row++) {
29-
for (int col = 0; col < SIZE; col++) {
30-
// Find an empty cell
31-
if (board[row][col] == EMPTY) {
32-
// Try digits 1-9
33-
for (int num = 1; num <= SIZE; num++) {
34-
if (isValid(board, row, col, num)) {
35-
// Place the number
36-
board[row][col] = num;
37-
38-
// Recursively try to solve the rest
39-
if (solveSudoku(board)) {
40-
return true;
41-
}
42-
43-
// Backtrack if no solution found
44-
board[row][col] = EMPTY;
45-
}
46-
}
47-
// No valid number found, backtrack
48-
return false;
49-
}
21+
private static final int SIZE = 9;
22+
private static final int SUBGRID_SIZE = 3;
23+
private static final int EMPTY = 0;
24+
25+
/**
26+
* Solves the given Sudoku board using backtracking. Modifies the board
27+
* in-place.
28+
*
29+
* @param board 9×9 2D array representing the Sudoku board (0 = empty cell)
30+
* @return true if a valid solution exists, false otherwise
31+
*/
32+
public static boolean solveSudoku(int[][] board) {
33+
for (int row = 0; row < SIZE; row++) {
34+
for (int col = 0; col < SIZE; col++) {
35+
// Find an empty cell
36+
if (board[row][col] == EMPTY) {
37+
// Try digits 1-9
38+
for (int num = 1; num <= SIZE; num++) {
39+
if (isValid(board, row, col, num)) {
40+
// Place the number
41+
board[row][col] = num;
42+
43+
// Recursively try to solve the rest
44+
if (solveSudoku(board)) {
45+
return true;
46+
}
47+
48+
// Backtrack if no solution found
49+
board[row][col] = EMPTY;
5050
}
51+
}
52+
// No valid number found, backtrack
53+
return false;
5154
}
52-
// All cells filled successfully
53-
return true;
55+
}
5456
}
55-
56-
/**
57-
* Checks if placing a number at a given position is valid.
58-
*
59-
* @param board the Sudoku board
60-
* @param row row index
61-
* @param col column index
62-
* @param num number to place (1-9)
63-
* @return true if placement is valid
64-
*/
65-
private static boolean isValid(int[][] board, int row, int col, int num) {
66-
// Check row constraint
67-
if (!isRowValid(board, row, num)) {
68-
return false;
69-
}
70-
71-
// Check column constraint
72-
if (!isColumnValid(board, col, num)) {
73-
return false;
74-
}
75-
76-
// Check 3×3 subgrid constraint
77-
if (!isSubgridValid(board, row, col, num)) {
78-
return false;
79-
}
80-
81-
return true;
57+
// All cells filled successfully
58+
return true;
59+
}
60+
61+
/**
62+
* Checks if placing a number at a given position is valid.
63+
*
64+
* @param board the Sudoku board
65+
* @param row row index
66+
* @param col column index
67+
* @param num number to place (1-9)
68+
* @return true if placement is valid
69+
*/
70+
private static boolean isValid(int[][] board, int row, int col, int num) {
71+
// Check row constraint
72+
if (!isRowValid(board, row, num)) {
73+
return false;
8274
}
8375

84-
/**
85-
* Checks if a number already exists in the given row.
86-
*/
87-
private static boolean isRowValid(int[][] board, int row, int num) {
88-
for (int col = 0; col < SIZE; col++) {
89-
if (board[row][col] == num) {
90-
return false;
91-
}
92-
}
93-
return true;
76+
// Check column constraint
77+
if (!isColumnValid(board, col, num)) {
78+
return false;
9479
}
9580

96-
/**
97-
* Checks if a number already exists in the given column.
98-
*/
99-
private static boolean isColumnValid(int[][] board, int col, int num) {
100-
for (int row = 0; row < SIZE; row++) {
101-
if (board[row][col] == num) {
102-
return false;
103-
}
104-
}
105-
return true;
81+
// Check 3×3 subgrid constraint
82+
if (!isSubgridValid(board, row, col, num)) {
83+
return false;
10684
}
10785

108-
/**
109-
* Checks if a number already exists in the 3×3 subgrid.
110-
*/
111-
private static boolean isSubgridValid(int[][] board, int row, int col, int num) {
112-
int subgridRow = row - row % SUBGRID_SIZE;
113-
int subgridCol = col - col % SUBGRID_SIZE;
114-
115-
for (int i = subgridRow; i < subgridRow + SUBGRID_SIZE; i++) {
116-
for (int j = subgridCol; j < subgridCol + SUBGRID_SIZE; j++) {
117-
if (board[i][j] == num) {
118-
return false;
119-
}
120-
}
121-
}
122-
return true;
86+
return true;
87+
}
88+
89+
/**
90+
* Checks if a number already exists in the given row.
91+
*
92+
* @param board the Sudoku board
93+
* @param row row index
94+
* @param num number to check
95+
* @return true if number is not in row
96+
*/
97+
private static boolean isRowValid(int[][] board, int row, int num) {
98+
for (int col = 0; col < SIZE; col++) {
99+
if (board[row][col] == num) {
100+
return false;
101+
}
123102
}
124-
125-
/**
126-
* Prints the Sudoku board in a readable format.
127-
*/
128-
public static void printBoard(int[][] board) {
129-
for (int row = 0; row < SIZE; row++) {
130-
if (row % SUBGRID_SIZE == 0 && row != 0) {
131-
System.out.println("-----------");
132-
}
133-
for (int col = 0; col < SIZE; col++) {
134-
if (col % SUBGRID_SIZE == 0 && col != 0) {
135-
System.out.print("|");
136-
}
137-
System.out.print(board[row][col]);
138-
}
139-
System.out.println();
103+
return true;
104+
}
105+
106+
/**
107+
* Checks if a number already exists in the given column.
108+
*
109+
* @param board the Sudoku board
110+
* @param col column index
111+
* @param num number to check
112+
* @return true if number is not in column
113+
*/
114+
private static boolean isColumnValid(int[][] board, int col, int num) {
115+
for (int row = 0; row < SIZE; row++) {
116+
if (board[row][col] == num) {
117+
return false;
118+
}
119+
}
120+
return true;
121+
}
122+
123+
/**
124+
* Checks if a number already exists in the 3×3 subgrid.
125+
*
126+
* @param board the Sudoku board
127+
* @param row row index
128+
* @param col column index
129+
* @param num number to check
130+
* @return true if number is not in subgrid
131+
*/
132+
private static boolean isSubgridValid(int[][] board, int row, int col,
133+
int num) {
134+
int subgridRow = row - row % SUBGRID_SIZE;
135+
int subgridCol = col - col % SUBGRID_SIZE;
136+
137+
for (int i = subgridRow; i < subgridRow + SUBGRID_SIZE; i++) {
138+
for (int j = subgridCol; j < subgridCol + SUBGRID_SIZE; j++) {
139+
if (board[i][j] == num) {
140+
return false;
140141
}
142+
}
141143
}
142-
143-
/**
144-
* Main method demonstrating Sudoku solver functionality.
145-
*/
146-
public static void main(String[] args) {
147-
// Example Sudoku puzzle (0 = empty cell)
148-
int[][] board = {
149-
{5, 3, 0, 0, 7, 0, 0, 0, 0},
150-
{6, 0, 0, 1, 9, 5, 0, 0, 0},
151-
{0, 9, 8, 0, 0, 0, 0, 6, 0},
152-
{8, 0, 0, 0, 6, 0, 0, 0, 3},
153-
{4, 0, 0, 8, 0, 3, 0, 0, 1},
154-
{7, 0, 0, 0, 2, 0, 0, 0, 6},
155-
{0, 6, 0, 0, 0, 0, 2, 8, 0},
156-
{0, 0, 0, 4, 1, 9, 0, 0, 5},
157-
{0, 0, 0, 0, 8, 0, 0, 7, 9}
158-
};
159-
160-
System.out.println("Sudoku Puzzle:");
161-
printBoard(board);
162-
163-
if (solveSudoku(board)) {
164-
System.out.println("\nSolved Sudoku:");
165-
printBoard(board);
166-
} else {
167-
System.out.println("\nNo solution exists for this Sudoku puzzle.");
144+
return true;
145+
}
146+
147+
/**
148+
* Prints the Sudoku board in a readable format.
149+
*
150+
* @param board the Sudoku board to print
151+
*/
152+
public static void printBoard(int[][] board) {
153+
for (int row = 0; row < SIZE; row++) {
154+
if (row % SUBGRID_SIZE == 0 && row != 0) {
155+
System.out.println("-----------");
156+
}
157+
for (int col = 0; col < SIZE; col++) {
158+
if (col % SUBGRID_SIZE == 0 && col != 0) {
159+
System.out.print("|");
168160
}
161+
System.out.print(board[row][col]);
162+
}
163+
System.out.println();
164+
}
165+
}
166+
167+
/**
168+
* Main method demonstrating Sudoku solver functionality.
169+
*
170+
* @param args command line arguments (not used)
171+
*/
172+
public static void main(String[] args) {
173+
// Example Sudoku puzzle (0 = empty cell)
174+
int[][] board = {
175+
{5, 3, 0, 0, 7, 0, 0, 0, 0},
176+
{6, 0, 0, 1, 9, 5, 0, 0, 0},
177+
{0, 9, 8, 0, 0, 0, 0, 6, 0},
178+
{8, 0, 0, 0, 6, 0, 0, 0, 3},
179+
{4, 0, 0, 8, 0, 3, 0, 0, 1},
180+
{7, 0, 0, 0, 2, 0, 0, 0, 6},
181+
{0, 6, 0, 0, 0, 0, 2, 8, 0},
182+
{0, 0, 0, 4, 1, 9, 0, 0, 5},
183+
{0, 0, 0, 0, 8, 0, 0, 7, 9}
184+
};
185+
186+
System.out.println("Sudoku Puzzle:");
187+
printBoard(board);
188+
189+
if (solveSudoku(board)) {
190+
System.out.println("\nSolved Sudoku:");
191+
printBoard(board);
192+
} else {
193+
System.out.println("\nNo solution exists for this Sudoku puzzle.");
169194
}
195+
}
170196
}

0 commit comments

Comments
 (0)