Skip to content

Commit e89728e

Browse files
snowanazl397985856
authored andcommitted
feat: Add LC 79 word search (azl397985856#98)
1 parent 20c5079 commit e89728e

12 files changed

+481
-0
lines changed

README.en.md

+1
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ The data structures mainly includes:
148148
- [0073.set-matrix-zeroes](./problems/73.set-matrix-zeroes.md )
149149
- [0075.sort-colors](./problems/75.sort-colors.md)
150150
- [0078.subsets](./problems/78.subsets.md)
151+
- [0079.word-search](./problems/79.word-search-en.md)
151152
- [0086.partition-list](./problems/86.partition-list.md)
152153
- [0090.subsets-ii](./problems/90.subsets-ii.md)
153154
- [0091.decode-ways](./problems/91.decode-ways.md)

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ leetcode 题解,记录自己的 leetcode 解题之路。
167167
- [0073.set-matrix-zeroes](./problems/73.set-matrix-zeroes.md )
168168
- [0075.sort-colors](./problems/75.sort-colors.md)
169169
- [0078.subsets](./problems/78.subsets.md)
170+
- [0079.word-search](./problems/79.word-search.md)
170171
- [0086.partition-list](./problems/86.partition-list.md)
171172
- [0090.subsets-ii](./problems/90.subsets-ii.md)
172173
- [0091.decode-ways](./problems/91.decode-ways.md)

assets/problems/79.word-search-1.png

70 KB
Loading

assets/problems/79.word-search-2.png

71.4 KB
Loading

assets/problems/79.word-search-3.png

62.5 KB
Loading

assets/problems/79.word-search-4.png

72.8 KB
Loading

assets/problems/79.word-search-5.png

51.8 KB
Loading

assets/problems/79.word-search-6.png

55.7 KB
Loading

assets/problems/79.word-search-7.png

59.1 KB
Loading
61.9 KB
Loading

problems/79.word-search-en.md

+242
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
## Problem
2+
https://leetcode.com/problems/word-search/
3+
4+
## Problem Description
5+
```
6+
Given a 2D board and a word, find if the word exists in the grid.
7+
8+
The word can be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once.
9+
10+
Example:
11+
12+
board =
13+
[
14+
['A','B','C','E'],
15+
['S','F','C','S'],
16+
['A','D','E','E']
17+
]
18+
19+
Given word = "ABCCED", return true.
20+
Given word = "SEE", return true.
21+
Given word = "ABCB", return false.
22+
```
23+
24+
## Solution
25+
26+
This problem does not give start position, or direction restriction, so
27+
1. Scan board, find starting position with matching word first letter
28+
2. From starting position, DFS (4 (up, down, left, right 4 directions) match word's rest letters
29+
3. For each visited letter, mark it as visited, here use `board[i][j] = '*'` to represent visited.
30+
4. If one direction cannot continue, backtracking, mark start position unvisited, mark `board[i][j] = word[start]`
31+
5. If found any matching, terminate
32+
6. Otherwise, no matching found, return false.
33+
34+
For example:
35+
36+
board, word:`SEE` as below pic:
37+
```
38+
1. Scan board, found board[1,0] = word[0],match word first letter。
39+
2. DFS(up, down, left, right 4 directions)
40+
41+
as below pic:
42+
```
43+
![word search 1](../assets/problems/79.word-search-en-1.png)
44+
45+
Staring position(1,0), check whether adjacent cells match word next letter `E`.
46+
```
47+
1. mark current position(1,0)as visited,board[1][0] = '*'
48+
2. Up(0,0)letter='A' not match,
49+
3. Down(2,0)letter='A',not match,
50+
4. Left(-1,0)out of board boundry,not match,
51+
5. right(1,1)letter='F',not match
52+
53+
as below pic:
54+
```
55+
![word search 2](../assets/problems/79.word-search-2.png)
56+
57+
Didn't find matching from starting position, so
58+
```
59+
1. backtracking,mart start position(1,0)as unvisited, board[1][0] = 'S'.
60+
2. scan board, find next start position(1,3)which match word first letter
61+
62+
as below pic:
63+
```
64+
![word search 3](../assets/problems/79.word-search-3.png)
65+
66+
New starting position(1,3),check whether adjacent cells match word next letter `E`.
67+
```
68+
1. mark current position(1, 3)as already visited,board[1][3] = '*'
69+
2. Up(0,3)letter='E', match, continue DFS search,refer position(0,3)DFS search steps.
70+
3. Down(2,3)letter='E',match, since #2 DFS didn't find word matching, continue DFS search, rfer to position (2, 3) DFS search steps.
71+
4. Left(1,2)letter='C',not match,
72+
5. Right(1,4)out of board boundry,not match
73+
74+
as below pic:
75+
```
76+
![word search 4](../assets/problems/79.word-search-4.png)
77+
78+
Start position(0,3), DFS,check whether adjacent cells match word next letter `E`
79+
```
80+
1. marck current position(0,3)already visited,board[0][3] = '*'
81+
2. Up (-1,3)out of board boundry,not match
82+
3. Down(1,3)already visited,
83+
4. Left(0,2)letter='C',not match
84+
5. Right(1,4)out of board boundry,not match
85+
86+
as below pic:
87+
```
88+
![word search 5](../assets/problems/79.word-search-5.png)
89+
90+
Start from position(0,3)not matching word, start position (2, 3) DFS search:
91+
```
92+
1. Backtracking,mark(0,3)as unvisited。board[0][3] = 'E'.
93+
2. Backtracking to next position(2,3),DFS,check whether adjacent cells match word next letter 'E'
94+
3. Up (1,3)visited, continue
95+
4. Down(3,3)out of board boundry,not match
96+
5. Left(2,2)letter='E', match
97+
6. Right(2,4)out of board boundry,not match
98+
99+
as below pic:
100+
```
101+
![word search 6](../assets/problems/79.word-search-6.png)
102+
103+
Found match with word, return `True`.
104+
![word search 7](../assets/problems/79.word-search-7.png)
105+
106+
#### Complexity Analysis
107+
- *Time Complexity:* `O(m*n) - m is number of board rows, n is number of board columns `
108+
- *Space Complexity:* `O(1) - no extra space`
109+
110+
>**Note**:if use Set or boolean[][] mark position visited,need extra space `O(m*n)`.
111+
112+
## Key Points
113+
114+
- Scan board, find start position which match word first letter, DFS
115+
- Remember visited letter
116+
- Backtracking if not found matching
117+
118+
## Code (`Java/Javascript/Python3`)
119+
*Java Code*
120+
```java
121+
public class LC79WordSearch {
122+
public boolean exist(char[][] board, String word) {
123+
if (board == null || board.length == 0 || board[0].length == 0
124+
|| word == null || word.length() == 0) return true;
125+
int rows = board.length;
126+
int cols = board[0].length;
127+
for (int r = 0; r < rows; r++) {
128+
for (int c = 0; c < cols; c++) {
129+
// scan board, start with word first character
130+
if (board[r][c] == word.charAt(0)) {
131+
if (helper(board, word, r, c, 0)) {
132+
return true;
133+
}
134+
}
135+
}
136+
}
137+
return false;
138+
}
139+
140+
private boolean helper(char[][] board, String word, int r, int c, int start) {
141+
// already match word all characters, return true
142+
if (start == word.length()) return true;
143+
if (!isValid(board, r, c) ||
144+
board[r][c] != word.charAt(start)) return false;
145+
// mark visited
146+
board[r][c] = '*';
147+
boolean res = helper(board, word, r + 1, c, start + 1)
148+
|| helper(board, word, r, c + 1, start + 1)
149+
|| helper(board, word, r - 1, c, start + 1)
150+
|| helper(board, word, r, c - 1, start + 1);
151+
// backtracking to start position
152+
board[r][c] = word.charAt(start);
153+
return res;
154+
}
155+
156+
private boolean isValid(char[][] board, int r, int c) {
157+
return r >= 0 && r < board.length && c >= 0 && c < board[0].length;
158+
}
159+
}
160+
```
161+
162+
*Python3 Code*
163+
```python
164+
class Solution:
165+
def exist(self, board: List[List[str]], word: str) -> bool:
166+
m = len(board)
167+
n = len(board[0])
168+
169+
def dfs(board, r, c, word, index):
170+
if index == len(word):
171+
return True
172+
if r < 0 or r >= m or c < 0 or c >= n or board[r][c] != word[index]:
173+
return False
174+
board[r][c] = '*'
175+
res = dfs(board, r - 1, c, word, index + 1) or dfs(board, r + 1, c, word, index + 1) or dfs(board, r, c - 1, word, index + 1) or dfs(board, r, c + 1, word, index + 1)
176+
board[r][c] = word[index]
177+
return res
178+
179+
for r in range(m):
180+
for c in range(n):
181+
if board[r][c] == word[0]:
182+
if dfs(board, r, c, word, 0):
183+
return True
184+
```
185+
186+
*Javascript Code* from [**@lucifer**](https://github.com/azl397985856)
187+
```javascript
188+
/*
189+
* @lc app=leetcode id=79 lang=javascript
190+
*
191+
* [79] Word Search
192+
*/
193+
function DFS(board, row, col, rows, cols, word, cur) {
194+
// 边界检查
195+
if (row >= rows || row < 0) return false;
196+
if (col >= cols || col < 0) return false;
197+
198+
const item = board[row][col];
199+
200+
if (item !== word[cur]) return false;
201+
202+
if (cur + 1 === word.length) return true;
203+
204+
// If use HashMap keep track visited letters, then need manual clear HashMap for each backtrack which needs extra space.
205+
// here we use a little trick
206+
board[row][col] = null;
207+
208+
// UP, DOWN, LEFT, RIGHT
209+
const res =
210+
DFS(board, row + 1, col, rows, cols, word, cur + 1) ||
211+
DFS(board, row - 1, col, rows, cols, word, cur + 1) ||
212+
DFS(board, row, col - 1, rows, cols, word, cur + 1) ||
213+
DFS(board, row, col + 1, rows, cols, word, cur + 1);
214+
215+
board[row][col] = item;
216+
217+
return res;
218+
}
219+
/**
220+
* @param {character[][]} board
221+
* @param {string} word
222+
* @return {boolean}
223+
*/
224+
var exist = function(board, word) {
225+
if (word.length === 0) return true;
226+
if (board.length === 0) return false;
227+
228+
const rows = board.length;
229+
const cols = board[0].length;
230+
231+
for (let i = 0; i < rows; i++) {
232+
for (let j = 0; j < cols; j++) {
233+
const hit = DFS(board, i, j, rows, cols, word, 0);
234+
if (hit) return true;
235+
}
236+
}
237+
return false;
238+
};
239+
```
240+
241+
## References
242+
1. [Backtracking Wiki](https://www.wikiwand.com/en/Backtracking)

0 commit comments

Comments
 (0)