package top100liked import ( "fmt" "slices" "testing" ) // https://leetcode.cn/problems/word-search/description/?envType=study-plan-v2&envId=top-100-liked func exist(board [][]byte, word string) bool { w := []byte(word) l := len(word) m := len(board) n := len(board[0]) // 下、右、上、左 move := [4][2]int{{1, 0}, {0, 1}, {-1, 0}, {0, -1}} // 减枝让耗时降低了很多 var boardCnt [128]int // 覆盖 ASCII,字母在范围内 for _, row := range board { for _, c := range row { boardCnt[c]++ } } var wordCnt [128]int for _, c := range w { wordCnt[c]++ } // 字符频次可行性预检。 扫一遍 board 统计各字符计数,若 word 中某字符出现次数超过 board 上的数量,直接 return false。 for _, char := range w { if boardCnt[char] < wordCnt[char] { return false } } // 词序翻转剪枝(算法层面最大收益)。 统计 board 中 word[0] 和 word[l-1] 的出现次数,若首字符比尾字符更常见,就把 word 反转后再搜——从稀有端开始DFS,能在更浅层就剪掉大量无效分支。 if boardCnt[0] > boardCnt[len(boardCnt)-1] { slices.Reverse(w) } var helper func(idx, row, col int) bool helper = func(idx, row, col int) bool { for _, v := range move { new_row := row + v[0] new_col := col + v[1] if new_row >= 0 && new_row < m && new_col >= 0 && new_col < n && w[idx] == board[new_row][new_col] { if idx == l-1 { return true } board[new_row][new_col] = '#' if helper(idx+1, new_row, new_col) { return true } board[new_row][new_col] = w[idx] } } return false } for i, row := range board { for j, col := range row { if col == w[0] { if l == 1 { return true } board[i][j] = '#' if helper(1, i, j) { return true } board[i][j] = w[0] } } } return false } func Test(t *testing.T) { fmt.Printf("%+v\n", exist([][]byte{{'A', 'B', 'C', 'E'}, {'S', 'F', 'C', 'S'}, {'A', 'D', 'E', 'E'}}, "ABCCED")) } func Test2(t *testing.T) { fmt.Printf("%+v\n", exist([][]byte{{'A', 'B', 'C', 'E'}, {'S', 'F', 'C', 'S'}, {'A', 'D', 'E', 'E'}}, "SEE")) } func Test3(t *testing.T) { fmt.Printf("%+v\n", exist([][]byte{{'A', 'B', 'C', 'E'}, {'S', 'F', 'C', 'S'}, {'A', 'D', 'E', 'E'}}, "ABCB")) }