刷题使我快乐,满脸开心.jpg

  • 来源:力扣(LeetCode)
  • 链接:https://leetcode.cn/problems/word-search/
  • 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题目

给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false

单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

示例 1:

输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
输出:true

示例 2:

输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "SEE"
输出:true

示例 3:

输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCB"
输出:false

提示:

  • m == board.length
  • n = board[i].length
  • 1 <= m, n <= 6
  • 1 <= word.length <= 15
  • boardword 仅由大小写英文字母组成

进阶:你可以使用搜索剪枝的技术来优化解决方案,使其在 board 更大的情况下可以更快解决问题?

思路

这道题思路其实挺简单的

  • 遍历找到起点之后启动搜索
  • 搜索时,分别向四个方向找下一个字符
  • 最后一个字符依然匹配则找到单词,否则找不到

这个很自然的就是一个回溯思路,然后离不开的一个优化思路就是进阶中提到的剪枝

  • 第一层,自然是字符串是否匹配,不匹配就直接断掉
  • 第二层,题中其实给了一个提示,那就是同一单元格的字母不能重复使用,这样就可以用一个数组来标识是否搜索过,进行剪枝了

基本上思路就是如此了,直接上代码,细节在注释

代码

func exist(board [][]byte, word string) bool {
	m, n := len(board), len(board[0])
	// 如果字符总个数都不够,直接false
	if m*n < len(word) {
		return false
	}

	// 记录是否已经扫描过,便于剪枝
	visit := make([][]bool, m)
	for i := range visit {
		visit[i] = make([]bool, n)
	}

	var check func(i, j, k int) bool
	check = func(i, j, k int) bool {
		// 剪枝1 当前字符不匹配则不用考虑
		if board[i][j] != word[k] {
			return false
		}
		// 字符匹配,且已经是最后一个字符,那么单词存在
		if k == len(word)-1 {
			return true
		}

        // 剪枝2 校验是否已经遍历过 
		visit[i][j] = true
		// 查看上元素
		if 0 <= (i-1) && (i-1) < m && !visit[i-1][j] {
			if check(i-1, j, k+1) {
				return true
			}
		}
		// 查看下元素
		if 0 <= (i+1) && (i+1) < m && !visit[i+1][j] {
			if check(i+1, j, k+1) {
				return true
			}
		}
		// 查看左元素
		if 0 <= (j-1) && (j-1) < n && !visit[i][j-1] {
			if check(i, j-1, k+1) {
				return true
			}
		}
		// 查看右元素
		if 0 <= (j+1) && (j+1) < n && !visit[i][j+1] {
			if check(i, j+1, k+1) {
				return true
			}
		}

		// 还原访问现场
		visit[i][j] = false
		return false
	}
	for i, row := range board {
		for j := range row {
			if check(i, j, 0) {
				return true
			}
		}
	}
	return false
}