Skip to content

Commit abc2ebc

Browse files
authored
Merge pull request #850 from debangi29/sudoku
Added solution to Leetcode 36(medium) , 37(hard) problems
2 parents 2c9d0b6 + 63cbf18 commit abc2ebc

File tree

2 files changed

+377
-0
lines changed

2 files changed

+377
-0
lines changed
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
---
2+
id: valid-sudoku
3+
title: Valid Sudoku
4+
difficulty: Medium
5+
sidebar_label: 0036-ValidSudoku
6+
tags:
7+
- Array
8+
- Hash Table
9+
- Matrix
10+
---
11+
12+
## Problem Description
13+
14+
| Problem Statement | Solution Link | LeetCode Profile |
15+
| :---------------- | :------------ | :--------------- |
16+
| [Valid Sudoku](https://leetcode.com/problems/valid-sudoku/description/) | [Valid Sudoku Solution on LeetCode](https://leetcode.com/problems/valid-sudoku/solutions/) | [Debangi Ghosh](https://leetcode.com/u/debangi_29/) |
17+
18+
## Problem Description
19+
20+
Determine if a $9 \times 9$ Sudoku board is valid. Only the filled cells need to be validated according to the following rules:
21+
22+
- Each row must contain the digits 1-9 without repetition.
23+
- Each column must contain the digits 1-9 without repetition.
24+
- Each of the nine $3 \times 3$ sub-boxes of the grid must contain the digits 1-9 without repetition.
25+
Note:
26+
27+
A Sudoku board (partially filled) could be valid but is not necessarily solvable.
28+
Only the filled cells need to be validated according to the mentioned rules.
29+
30+
### Examples
31+
32+
#### Example 1:
33+
34+
**Input**: board =
35+
```
36+
[["5","3",".",".","7",".",".",".","."]
37+
,["6",".",".","1","9","5",".",".","."]
38+
,[".","9","8",".",".",".",".","6","."]
39+
,["8",".",".",".","6",".",".",".","3"]
40+
,["4",".",".","8",".","3",".",".","1"]
41+
,["7",".",".",".","2",".",".",".","6"]
42+
,[".","6",".",".",".",".","2","8","."]
43+
,[".",".",".","4","1","9",".",".","5"]
44+
,[".",".",".",".","8",".",".","7","9"]]
45+
```
46+
**Output**: true
47+
#### Example 2:
48+
49+
- **Input:** board =
50+
```
51+
[["8","3",".",".","7",".",".",".","."]
52+
,["6",".",".","1","9","5",".",".","."]
53+
,[".","9","8",".",".",".",".","6","."]
54+
,["8",".",".",".","6",".",".",".","3"]
55+
,["4",".",".","8",".","3",".",".","1"]
56+
,["7",".",".",".","2",".",".",".","6"]
57+
,[".","6",".",".",".",".","2","8","."]
58+
,[".",".",".","4","1","9",".",".","5"]
59+
,[".",".",".",".","8",".",".","7","9"]]
60+
```
61+
**Output:** false
62+
63+
**Explanation**: Same as Example 1, except with the 5 in the top left corner being modified to 8. Since there are two 8's in the top left $3 \times 3$ sub-box, it is invalid.
64+
65+
66+
### Constraints
67+
68+
- board.length == 9
69+
- board[i].length == 9
70+
- board[i][j] is a digit 1-9 or '.'.
71+
72+
### Approach
73+
74+
✔ HashSet Initialization: The algorithm uses a HashSet (seen) to keep track of unique elements encountered during the traversal of the Sudoku board.
75+
76+
✔ Traversing the Board: The algorithm uses nested loops to iterate through each cell of the 9x9 Sudoku board.
77+
78+
✔ Checking Rows, Columns, and Sub-boxes
79+
👉 For each non-empty cell (cell value not equal to ‘.’), the algorithm checks if the current digit is already present in the same row, column, or $3 \times 3$ sub-box using HashSet operations.
80+
81+
👉 Unique string representations are used to identify rows, columns, and sub-boxes. (don’t worry, will explain it 😊)
82+
83+
✔ Returning Validity:
84+
85+
👉 If all the checks pass for a given cell, the digit is added to the HashSet to mark it as seen.
86+
87+
👉 The traversal continues until all cells have been processed.
88+
89+
👉 If any violation is detected during the traversal (i.e., a digit is repeated in a row, column, or sub-box), the function returns false, indicating that the Sudoku board is not valid.
90+
91+
👉 If the traversal completes without encountering any violations, the function returns true. That’s mean Sudolu board is valid.
92+
93+
### Solution Code
94+
95+
#### Python
96+
97+
```
98+
class Solution:
99+
def isValidSudoku(self, board: List[List[str]]) -> bool:
100+
seen = set()
101+
102+
for i in range(9):
103+
for j in range(9):
104+
c = board[i][j]
105+
if c == '.':
106+
continue
107+
if c + '@row ' + str(i) in seen or \
108+
c + '@col ' + str(j) in seen or \
109+
c + '@box ' + str(i // 3) + str(j // 3) in seen:
110+
return False
111+
seen.add(c + '@row ' + str(i))
112+
seen.add(c + '@col ' + str(j))
113+
seen.add(c + '@box ' + str(i // 3) + str(j // 3))
114+
115+
return True
116+
117+
```
118+
119+
#### Java
120+
121+
```
122+
class Solution {
123+
public boolean isValidSudoku(char[][] board) {
124+
Set<String> seen = new HashSet<>();
125+
126+
for (int i = 0; i < 9; ++i)
127+
for (int j = 0; j < 9; ++j) {
128+
if (board[i][j] == '.')
129+
continue;
130+
final char c = board[i][j];
131+
if (!seen.add(c + "@row" + i) || //
132+
!seen.add(c + "@col" + j) || //
133+
!seen.add(c + "@box" + i / 3 + j / 3))
134+
return false;
135+
}
136+
137+
return true;
138+
}
139+
}
140+
```
141+
142+
#### C++
143+
144+
```
145+
class Solution {
146+
public:
147+
bool isValidSudoku(vector<vector<char>>& board) {
148+
unordered_set<string> seen;
149+
150+
for (int i = 0; i < 9; ++i)
151+
for (int j = 0; j < 9; ++j) {
152+
if (board[i][j] == '.')
153+
continue;
154+
const string c(1, board[i][j]);
155+
if (!seen.insert(c + "@row" + to_string(i)).second ||
156+
!seen.insert(c + "@col" + to_string(j)).second ||
157+
!seen.insert(c + "@box" + to_string(i / 3) + to_string(j / 3))
158+
.second)
159+
return false;
160+
}
161+
162+
return true;
163+
}
164+
};
165+
```
166+
167+
### Conclusion
168+
169+
The above solution efficiently finds if the sudoku configuration is valid or not in $O(1)$ time complexity.
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
---
2+
id: sudoku-solver
3+
title: Sudoku Solver
4+
difficulty: Hard
5+
sidebar_label: 0037-ValidSudoku
6+
tags:
7+
- Array
8+
- Hash Table
9+
- Matrix
10+
- Backtracking
11+
---
12+
13+
## Problem Description
14+
15+
| Problem Statement | Solution Link | LeetCode Profile |
16+
| :---------------- | :------------ | :--------------- |
17+
| [Sudoku Solver](https://leetcode.com/problems/sudoku-solver/description/) | [Sudoku Solver Solution on LeetCode](https://leetcode.com/problems/sudoku-solver/solutions/) | [Debangi Ghosh](https://leetcode.com/u/debangi_29/) |
18+
19+
## Problem Description
20+
21+
Write a program to solve a Sudoku puzzle by filling the empty cells.
22+
23+
A sudoku solution must satisfy all of the following rules:
24+
25+
1. Each of the digits 1-9 must occur exactly once in each row.
26+
2. Each of the digits 1-9 must occur exactly once in each column.
27+
3. Each of the digits 1-9 must occur exactly once in each of the 9 $3 \times 3$ sub-boxes of the grid.
28+
29+
The '.' character indicates empty cells.
30+
31+
32+
33+
### Examples
34+
35+
#### Example 1:
36+
37+
**Input**: board =
38+
```
39+
[["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"]]
40+
```
41+
42+
**Output**:
43+
```
44+
[["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"]]
45+
```
46+
47+
**Explanation**: The input board is shown above and the only valid solution is shown below:
48+
49+
50+
### Constraints
51+
52+
- board.length == 9
53+
- board[i].length == 9
54+
- board[i][j] is a digit 1-9 or '.'.
55+
- It is guaranteed that the input board has only one solution.
56+
57+
### Approach
58+
59+
👉 Iterate Through Each Cell: The algorithm iterates through each cell of the Sudoku board
60+
61+
👉 Empty Cell Check: If the current cell is empty (contains ‘.’), the algorithm proceeds to try different numbers (from ‘1’ to ‘9’) in that cell
62+
63+
👉 Number Placement: For each number, the algorithm checks if placing that number in the current cell is valid according to the Sudoku rules (no repetition in the same row, column, or $3 \times 3$ sub-box).
64+
65+
👉 Recursive Exploration: If placing a number is valid, the algorithm sets that number in the cell and recursively explores the next empty cell.
66+
67+
👉 Backtracking: If the recursive exploration leads to an invalid solution, the algorithm backtracks by undoing the choice (resetting the cell to ‘.’) and trying the next number.
68+
69+
👉 Solution Check: The algorithm continues exploring possibilities until a valid solution is found, or it exhaustively searches all possibilities.
70+
71+
### Solution Code
72+
73+
#### Python
74+
75+
```
76+
class Solution:
77+
def solveSudoku(self, board: List[List[str]]) -> None:
78+
def isValid(row: int, col: int, c: str) -> bool:
79+
for i in range(9):
80+
if board[i][col] == c or \
81+
board[row][i] == c or \
82+
board[3 * (row // 3) + i // 3][3 * (col // 3) + i % 3] == c:
83+
return False
84+
return True
85+
86+
def solve(s: int) -> bool:
87+
if s == 81:
88+
return True
89+
90+
i = s // 9
91+
j = s % 9
92+
93+
if board[i][j] != '.':
94+
return solve(s + 1)
95+
96+
for c in string.digits[1:]:
97+
if isValid(i, j, c):
98+
board[i][j] = c
99+
if solve(s + 1):
100+
return True
101+
board[i][j] = '.'
102+
103+
return False
104+
105+
solve(0)
106+
107+
```
108+
109+
#### Java
110+
111+
```
112+
class Solution {
113+
public void solveSudoku(char[][] board) {
114+
dfs(board, 0);
115+
}
116+
117+
private boolean dfs(char[][] board, int s) {
118+
if (s == 81)
119+
return true;
120+
121+
final int i = s / 9;
122+
final int j = s % 9;
123+
124+
if (board[i][j] != '.')
125+
return dfs(board, s + 1);
126+
127+
for (char c = '1'; c <= '9'; ++c)
128+
if (isValid(board, i, j, c)) {
129+
board[i][j] = c;
130+
if (dfs(board, s + 1))
131+
return true;
132+
board[i][j] = '.';
133+
}
134+
135+
return false;
136+
}
137+
138+
private boolean isValid(char[][] board, int row, int col, char c) {
139+
for (int i = 0; i < 9; ++i)
140+
if (board[i][col] == c || board[row][i] == c ||
141+
board[3 * (row / 3) + i / 3][3 * (col / 3) + i % 3] == c)
142+
return false;
143+
return true;
144+
}
145+
}
146+
```
147+
148+
#### C++
149+
150+
```
151+
class Solution {
152+
public:
153+
void solveSudoku(vector<vector<char>>& board) {
154+
solve(board, 0);
155+
}
156+
157+
private:
158+
bool solve(vector<vector<char>>& board, int s) {
159+
if (s == 81)
160+
return true;
161+
162+
const int i = s / 9;
163+
const int j = s % 9;
164+
165+
if (board[i][j] != '.')
166+
return solve(board, s + 1);
167+
168+
for (char c = '1'; c <= '9'; ++c)
169+
if (isValid(board, i, j, c)) {
170+
board[i][j] = c;
171+
if (solve(board, s + 1))
172+
return true;
173+
board[i][j] = '.';
174+
}
175+
176+
return false;
177+
}
178+
179+
bool isValid(vector<vector<char>>& board, int row, int col, char c) {
180+
for (int i = 0; i < 9; ++i)
181+
if (board[i][col] == c || board[row][i] == c ||
182+
board[3 * (row / 3) + i / 3][3 * (col / 3) + i % 3] == c)
183+
return false;
184+
return true;
185+
}
186+
};
187+
188+
```
189+
190+
### Conclusion
191+
192+
✅ Time Complexity:
193+
194+
✔ The solve method uses a backtracking approach to explore the solution space.
195+
196+
✔ In the worst case, the algorithm tries out all possibilities for each empty cell until a valid solution is found or all possibilities are exhausted.
197+
198+
✔ The time complexity of the backtracking algorithm is typically exponential, but in practice, it tends to be much less than the worst case.
199+
200+
✔ Therefore, we often express the time complexity of backtracking algorithms using Big O notation as $O(b^d)$, where b is the branching factor (average number of choices at each decision point) and d is the depth of the recursion tree.
201+
202+
✅ Space Complexity:
203+
204+
✔ The space complexity is determined by the recursive call stack during the backtracking process.
205+
206+
✔ In the worst case, the depth of the recursion tree can be equal to the number of empty cells on the Sudoku board.
207+
208+
✔ Therefore, the space complexity is $O(bd)$, where b is the branching factor and d is the depth of the recursion tree.

0 commit comments

Comments
 (0)