Skip to content

Commit 79fa1ea

Browse files
committed
优化79
1 parent c98d5dc commit 79fa1ea

File tree

3 files changed

+50
-12
lines changed

3 files changed

+50
-12
lines changed

docs/0079-word-search.adoc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,17 @@ image::images/0079-03.jpg[{image_attr}]
4646

4747
== 思路分析
4848

49+
典型的回溯题目,常规剪枝技巧如下:
50+
4951
image:images/0079-01.png[{image_attr}]
5052

5153
image:images/0079-02.png[{image_attr}]
5254

55+
除了常规剪枝技巧外,还有两个优化点:
56+
57+
. 先判断字母出现次数是否满足要求。网友戏称为可行性剪枝。
58+
. 如果结尾字母出现次数更少,则将单词翻转,从尾部开始查找,这样可以更少回溯。网友戏称为顺序剪枝。
59+
5360
[[src-0079]]
5461
[tabs]
5562
====

logbook/202503.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1917,7 +1917,7 @@ endif::[]
19171917
|{counter:codes2503}
19181918
|{leetcode_base_url}/word-search/[79. 单词搜索^]
19191919
|{doc_base_url}/0079-word-search.adoc[题解]
1920-
|✅ 回溯。为了尽可能高效,找到就返回。
1920+
|✅ 回溯。为了尽可能高效,找到就返回。有两个优化点:①先判断字母出现次数是否满足要求;②如果结尾字母出现次数更少,则将单词翻转,从尾部开始查找,这样可以更少回溯。
19211921

19221922
|===
19231923

src/main/java/com/diguage/algo/leetcode/_0079_WordSearch_3.java

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,52 @@ public class _0079_WordSearch_3 {
88
* @since 2025-11-15 08:52:34
99
*/
1010
public boolean exist(char[][] board, String word) {
11+
// 优化一:检查字母出现次数
12+
char[] counter = new char[52];
13+
for (char[] chars : board) {
14+
for (char c : chars) {
15+
counter[getIndex(c)]++;
16+
}
17+
}
18+
char[] cnt = new char[52];
19+
for (char c : word.toCharArray()) {
20+
cnt[getIndex(c)]++;
21+
}
22+
for (int i = 0; i < cnt.length; i++) {
23+
if (cnt[i] > counter[i]) {
24+
return false;
25+
}
26+
}
27+
28+
// 优化二:如果最后字符出现次数更小,则从它开始,回溯次数更少
29+
int ti = getIndex(word.charAt(word.length() - 1));
30+
int hi = getIndex(word.charAt(0));
31+
if (cnt[ti] < cnt[hi]) {
32+
word = new StringBuilder(word).reverse().toString();
33+
}
34+
35+
// 回溯查找
1136
for (int c = 0; c < board.length; c++) {
1237
for (int r = 0; r < board[c].length; r++) {
13-
if (board[c][r] == word.charAt(0)) {
14-
boolean found = backtrack(board, word, c, r, 0);
15-
if (found) {
16-
return true;
17-
}
38+
boolean found = backtrack(board, c, r, word, 0);
39+
if (found) {
40+
return true;
1841
}
1942
}
2043
}
2144
return false;
2245
}
2346

24-
private boolean backtrack(char[][] board, String word,
25-
int column, int row, int index) {
47+
private int getIndex(char c) {
48+
int index = c - 'A';
49+
if (c >= 'a') {
50+
index = (c - 'a') + 26;
51+
}
52+
return index;
53+
}
54+
55+
private boolean backtrack(char[][] board, int column, int row,
56+
String word, int index) {
2657
if (index == word.length()) {
2758
return true;
2859
}
@@ -33,22 +64,22 @@ private boolean backtrack(char[][] board, String word,
3364
}
3465
board[column][row] = '.';
3566
// 上
36-
boolean found = backtrack(board, word, column - 1, row, index + 1);
67+
boolean found = backtrack(board, column - 1, row, word, index + 1);
3768
if (found) {
3869
return true;
3970
}
4071
// 下
41-
found = backtrack(board, word, column + 1, row, index + 1);
72+
found = backtrack(board, column + 1, row, word, index + 1);
4273
if (found) {
4374
return true;
4475
}
4576
// 左
46-
found = backtrack(board, word, column, row - 1, index + 1);
77+
found = backtrack(board, column, row - 1, word, index + 1);
4778
if (found) {
4879
return true;
4980
}
5081
// 右
51-
found = backtrack(board, word, column, row + 1, index + 1);
82+
found = backtrack(board, column, row + 1, word, index + 1);
5283
if (found) {
5384
return true;
5485
}

0 commit comments

Comments
 (0)