-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathWordSearchIi.java
More file actions
182 lines (163 loc) · 6.05 KB
/
Copy pathWordSearchIi.java
File metadata and controls
182 lines (163 loc) · 6.05 KB
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
/**
* <p>给定一个 <code>m x n</code> 二维字符网格 <code>board</code><strong> </strong>和一个单词(字符串)列表 <code>words</code>,找出所有同时在二维网格和字典中出现的单词。</p>
*
* <p>单词必须按照字母顺序,通过 <strong>相邻的单元格</strong> 内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。</p>
*
* <p> </p>
*
* <p><strong>示例 1:</strong></p>
* <img alt="" src="https://assets.leetcode.com/uploads/2020/11/07/search1.jpg" style="width: 322px; height: 322px;" />
* <pre>
* <strong>输入:</strong>board = [["o","a","a","n"],["e","t","a","e"],["i","h","k","r"],["i","f","l","v"]], words = ["oath","pea","eat","rain"]
* <strong>输出:</strong>["eat","oath"]
* </pre>
*
* <p><strong>示例 2:</strong></p>
* <img alt="" src="https://assets.leetcode.com/uploads/2020/11/07/search2.jpg" style="width: 162px; height: 162px;" />
* <pre>
* <strong>输入:</strong>board = [["a","b"],["c","d"]], words = ["abcb"]
* <strong>输出:</strong>[]
* </pre>
*
* <p> </p>
*
* <p><strong>提示:</strong></p>
*
* <ul>
* <li><code>m == board.length</code></li>
* <li><code>n == board[i].length</code></li>
* <li><code>1 <= m, n <= 12</code></li>
* <li><code>board[i][j]</code> 是一个小写英文字母</li>
* <li><code>1 <= words.length <= 3 * 10<sup>4</sup></code></li>
* <li><code>1 <= words[i].length <= 10</code></li>
* <li><code>words[i]</code> 由小写英文字母组成</li>
* <li><code>words</code> 中的所有字符串互不相同</li>
* </ul>
* <div><div>Related Topics</div><div><li>字典树</li><li>数组</li><li>字符串</li><li>回溯</li><li>矩阵</li></div></div><br><div><li>👍 598</li><li>👎 0</li></div>
*/
package leetcode7;
import java.util.*;
public class WordSearchIi {
public static void main(String[] args) {
new WordSearchIi().new Solution().findWords(
new char[][]{
{'o', 'a', 'a', 'n'},
{'e', 't', 'a', 'e'},
{'i', 'h', 'k', 'r'},
{'i', 'f', 'l', 'v'}},
new String[]{"oath", "pea", "eat", "rain"});
}
/**
* DFS + 回溯
* 时间复杂度高
* 注:回溯时注意不要漏了恢复当前层,一定要恢复全
*/
class Solution {
private int[][] pointList = new int[][]{{0, 1}, {0, -1}, {1, 0}, {-1, 0},};
public List<String> findWords(char[][] board, String[] words) {
List<String> res = new ArrayList<>();
for (String word : words) {
String wordRes = calc(board, res, word);
if (wordRes != null) {
res.add(wordRes);
}
}
return res;
}
private String calc(char[][] board, List<String> res, String word) {
for (int x = 0; x <= board.length; x++) {
for (int y = 0; y <= board[0].length; y++) {
if (solve(board, word, x, y, 0)) {
return word;
}
}
}
return null;
}
private boolean solve(char[][] board, String word, int x, int y, int level) {
int xMax = board.length - 1;
int yMax = board[0].length - 1;
if (level >= word.length()) {
return true;
}
if (x < 0 || y < 0 || x > xMax || y > yMax
|| word.charAt(level) != board[x][y]) {
return false;
}
board[x][y] = 0;
for (int[] p : pointList) {
if (solve(board, word, x + p[0], y + p[1], level + 1)) {
board[x][y] = word.charAt(level);
return true;
}
}
board[x][y] = word.charAt(level);
return false;
}
}
/**
* 字典树
* 时间复杂度高
* 暂不研究了
*/
class Solution1 {
int[][] addr = new int[][]{
{0, 1},
{0, -1},
{-1, 0},
{1, 0},
};
public List<String> findWords(char[][] board, String[] words) {
Set<String> res = new HashSet<>();
Trie trie = new Trie();
for (String word : words) {
trie.insert(word);
}
for (int x = 0; x < board.length; x++) {
for (int y = 0; y < board[0].length; y++) {
dfs(x, y, "", board, res, trie);
}
}
return new ArrayList<>(res);
}
private void dfs(int x, int y, String str, char[][] board, Set<String> res, Trie trie) {
if (trie == null) {
return;
}
if (trie.end) {
res.add(str);
}
if (x < 0 || y < 0 || x >= board.length || y >= board[0].length || board[x][y] == 0) {
return;
}
Trie node = trie.map.get(board[x][y]);
if (node == null) {
return;
}
trie = node;
char backup = board[x][y];
board[x][y] = 0;
for (int[] arr : addr) {
dfs(x + arr[0], y + arr[1], str + backup, board, res, trie);
}
board[x][y] = backup;
}
/**
* 一定要注意:操作的对象应来自于获取到的Trie对象,而不能直接用this
*/
public class Trie {
Map<Character, Trie> map = new HashMap<>();
boolean end;
public void insert(String s) {
Trie trie = this;
for (char c : s.toCharArray()) {
if (trie.map.get(c) == null) {
trie.map.put(c, new Trie());
}
trie = trie.map.get(c);
}
trie.end = true;
}
}
}
}