Skip to content

Commit 0977ccf

Browse files
committed
Add Sudoku Solver using Backtracking algorithm
- Implements backtracking algorithm to solve 9x9 Sudoku puzzles - Includes isValid() method to check Sudoku constraints - Includes solveSudoku() method with recursive backtracking - Adds comprehensive unit tests covering multiple scenarios - Tests include solvable, unsolvable, empty, and difficult puzzles - Includes example usage in main method with formatted output - Documents time complexity O(9^m) and space complexity O(m) Fixes #6929
1 parent 80b215c commit 0977ccf

File tree

2 files changed

+199
-127
lines changed

2 files changed

+199
-127
lines changed

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

Lines changed: 89 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -2,156 +2,143 @@
22

33
/**
44
* Sudoku Solver using Backtracking Algorithm
5-
* Solves a 9x9 Sudoku puzzle by filling empty cells with valid digits (1-9)
6-
*
7-
* @author Navadeep0007
5+
*
6+
* This class implements a backtracking algorithm to solve a 9x9 Sudoku puzzle.
7+
* The algorithm systematically tries valid numbers in empty cells and backtracks
8+
* when it encounters an invalid state.
9+
*
10+
* Time Complexity: O(9^m) where m is the number of empty cells
11+
* Space Complexity: O(m) for the recursion stack
12+
*
13+
* @author Raghu0703
814
*/
915
public final class SudokuSolver {
10-
16+
1117
private static final int GRID_SIZE = 9;
12-
private static final int SUBGRID_SIZE = 3;
1318
private static final int EMPTY_CELL = 0;
1419

1520
private SudokuSolver() {
16-
// Utility class, prevent instantiation
21+
// Utility class, no instantiation
1722
}
1823

1924
/**
20-
* Solves the Sudoku puzzle using backtracking
21-
*
22-
* @param board 9x9 Sudoku board with 0 representing empty cells
23-
* @return true if puzzle is solved, false otherwise
25+
* Checks if placing a number at a given position is valid according to Sudoku rules
26+
*
27+
* @param board the Sudoku board
28+
* @param row the row index
29+
* @param col the column index
30+
* @param num the number to place
31+
* @return true if the placement is valid, false otherwise
2432
*/
25-
public static boolean solveSudoku(int[][] board) {
26-
if (board == null || board.length != GRID_SIZE) {
27-
return false;
33+
private static boolean isValid(int[][] board, int row, int col, int num) {
34+
// Check if num is already in the row
35+
for (int i = 0; i < GRID_SIZE; i++) {
36+
if (board[row][i] == num) {
37+
return false;
38+
}
2839
}
2940

30-
for (int row = 0; row < GRID_SIZE; row++) {
31-
if (board[row].length != GRID_SIZE) {
41+
// Check if num is already in the column
42+
for (int i = 0; i < GRID_SIZE; i++) {
43+
if (board[i][col] == num) {
3244
return false;
3345
}
3446
}
3547

36-
return solve(board);
48+
// Check if num is already in the 3x3 subgrid
49+
int subgridRowStart = row - row % 3;
50+
int subgridColStart = col - col % 3;
51+
for (int i = subgridRowStart; i < subgridRowStart + 3; i++) {
52+
for (int j = subgridColStart; j < subgridColStart + 3; j++) {
53+
if (board[i][j] == num) {
54+
return false;
55+
}
56+
}
57+
}
58+
59+
return true;
3760
}
3861

3962
/**
40-
* Recursive helper method to solve the Sudoku puzzle
41-
*
42-
* @param board the Sudoku board
43-
* @return true if solution is found, false otherwise
63+
* Solves the Sudoku puzzle using backtracking
64+
*
65+
* @param board the Sudoku board (0 represents empty cells)
66+
* @return true if the puzzle is solvable, false otherwise
4467
*/
45-
private static boolean solve(int[][] board) {
68+
public static boolean solveSudoku(int[][] board) {
4669
for (int row = 0; row < GRID_SIZE; row++) {
4770
for (int col = 0; col < GRID_SIZE; col++) {
71+
// Find an empty cell
4872
if (board[row][col] == EMPTY_CELL) {
49-
for (int number = 1; number <= GRID_SIZE; number++) {
50-
if (isValidPlacement(board, row, col, number)) {
51-
board[row][col] = number;
73+
// Try numbers 1 through 9
74+
for (int num = 1; num <= GRID_SIZE; num++) {
75+
if (isValid(board, row, col, num)) {
76+
// Place the number
77+
board[row][col] = num;
5278

53-
if (solve(board)) {
79+
// Recursively try to solve the rest
80+
if (solveSudoku(board)) {
5481
return true;
5582
}
5683

57-
// Backtrack
84+
// Backtrack: undo the placement
5885
board[row][col] = EMPTY_CELL;
5986
}
6087
}
88+
// No valid number found, trigger backtracking
6189
return false;
6290
}
6391
}
6492
}
93+
// All cells filled successfully
6594
return true;
6695
}
6796

6897
/**
69-
* Checks if placing a number at given position is valid
70-
*
71-
* @param board the Sudoku board
72-
* @param row row index
73-
* @param col column index
74-
* @param number number to place (1-9)
75-
* @return true if placement is valid, false otherwise
98+
* Prints the Sudoku board in a formatted manner
99+
*
100+
* @param board the Sudoku board to print
76101
*/
77-
private static boolean isValidPlacement(int[][] board, int row, int col, int number) {
78-
return !isNumberInRow(board, row, number) && !isNumberInColumn(board, col, number) && !isNumberInSubgrid(board, row, col, number);
79-
}
80-
81-
/**
82-
* Checks if number exists in the given row
83-
*
84-
* @param board the Sudoku board
85-
* @param row row index
86-
* @param number number to check
87-
* @return true if number exists in row, false otherwise
88-
*/
89-
private static boolean isNumberInRow(int[][] board, int row, int number) {
90-
for (int col = 0; col < GRID_SIZE; col++) {
91-
if (board[row][col] == number) {
92-
return true;
93-
}
94-
}
95-
return false;
96-
}
97-
98-
/**
99-
* Checks if number exists in the given column
100-
*
101-
* @param board the Sudoku board
102-
* @param col column index
103-
* @param number number to check
104-
* @return true if number exists in column, false otherwise
105-
*/
106-
private static boolean isNumberInColumn(int[][] board, int col, int number) {
107-
for (int row = 0; row < GRID_SIZE; row++) {
108-
if (board[row][col] == number) {
109-
return true;
110-
}
111-
}
112-
return false;
113-
}
114-
115-
/**
116-
* Checks if number exists in the 3x3 subgrid
117-
*
118-
* @param board the Sudoku board
119-
* @param row row index
120-
* @param col column index
121-
* @param number number to check
122-
* @return true if number exists in subgrid, false otherwise
123-
*/
124-
private static boolean isNumberInSubgrid(int[][] board, int row, int col, int number) {
125-
int subgridRowStart = row - row % SUBGRID_SIZE;
126-
int subgridColStart = col - col % SUBGRID_SIZE;
127-
128-
for (int i = subgridRowStart; i < subgridRowStart + SUBGRID_SIZE; i++) {
129-
for (int j = subgridColStart; j < subgridColStart + SUBGRID_SIZE; j++) {
130-
if (board[i][j] == number) {
131-
return true;
132-
}
133-
}
134-
}
135-
return false;
136-
}
137-
138-
/**
139-
* Prints the Sudoku board
140-
*
141-
* @param board the Sudoku board
142-
*/
143-
public static void printBoard(int[][] board) {
102+
private static void printBoard(int[][] board) {
144103
for (int row = 0; row < GRID_SIZE; row++) {
145-
if (row % SUBGRID_SIZE == 0 && row != 0) {
104+
if (row % 3 == 0 && row != 0) {
146105
System.out.println("-----------");
147106
}
148107
for (int col = 0; col < GRID_SIZE; col++) {
149-
if (col % SUBGRID_SIZE == 0 && col != 0) {
108+
if (col % 3 == 0 && col != 0) {
150109
System.out.print("|");
151110
}
152111
System.out.print(board[row][col]);
153112
}
154113
System.out.println();
155114
}
156115
}
116+
117+
/**
118+
* Example usage of the Sudoku Solver
119+
*/
120+
public static void main(String[] args) {
121+
// Example Sudoku puzzle (0 represents empty cells)
122+
int[][] board = {
123+
{5, 3, 0, 0, 7, 0, 0, 0, 0},
124+
{6, 0, 0, 1, 9, 5, 0, 0, 0},
125+
{0, 9, 8, 0, 0, 0, 0, 6, 0},
126+
{8, 0, 0, 0, 6, 0, 0, 0, 3},
127+
{4, 0, 0, 8, 0, 3, 0, 0, 1},
128+
{7, 0, 0, 0, 2, 0, 0, 0, 6},
129+
{0, 6, 0, 0, 0, 0, 2, 8, 0},
130+
{0, 0, 0, 4, 1, 9, 0, 0, 5},
131+
{0, 0, 0, 0, 8, 0, 0, 7, 9}
132+
};
133+
134+
System.out.println("Original Sudoku Puzzle:");
135+
printBoard(board);
136+
137+
if (solveSudoku(board)) {
138+
System.out.println("\nSolved Sudoku:");
139+
printBoard(board);
140+
} else {
141+
System.out.println("\nNo solution exists for this Sudoku puzzle.");
142+
}
143+
}
157144
}

0 commit comments

Comments
 (0)