LeetCode 79 单词搜索

给定一个 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
  • board 和 word 仅由大小写英文字母组成

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

解题:

func exist(board [][]byte, word string) bool {
	b := make([][]bool, len(board))
	for i, v := range board {
		b[i] = make([]bool, len(v))
	}
	l, m, n := len(word), len(board), len(board[0])
	var search func(i, j, k int) bool
	search = func(i, j, k int) bool {
		if board[i][j] == word[k] {
			if k+1 == l {
				return true
			}
			b[i][j] = true
			if i-1 >= 0 && !b[i-1][j] && search(i-1, j, k+1) {
				return true
			}
			if i+1 < m && !b[i+1][j] && search(i+1, j, k+1) {
				return true
			}
			if j-1 >= 0 && !b[i][j-1] && search(i, j-1, k+1) {
				return true
			}
			if j+1 < n && !b[i][j+1] && search(i, j+1, k+1) {
				return true
			}
		}
		b[i][j] = false
		return false
	}
	for i, v := range board {
		for j, vv := range v {
			if vv == word[0] && search(i, j, 0) {
				return true
			}
		}
	}
	return false
}

官方解答:

1.回溯

type pair struct{ x, y int }

var directions = []pair{{-1, 0}, {1, 0}, {0, -1}, {0, 1}} // 上下左右

func exist(board [][]byte, word string) bool {
	h, w := len(board), len(board[0])
	vis := make([][]bool, h)
	for i := range vis {
		vis[i] = make([]bool, w)
	}
	var check func(i, j, k int) bool
	check = func(i, j, k int) bool {
		if board[i][j] != word[k] { // 剪枝:当前字符不匹配
			return false
		}
		if k == len(word)-1 { // 单词存在于网格中
			return true
		}
		vis[i][j] = true
		defer func() { vis[i][j] = false }() // 回溯时还原已访问的单元格
		for _, dir := range directions {
			if newI, newJ := i+dir.x, j+dir.y; 0 <= newI && newI < h && 0 <= newJ && newJ < w && !vis[newI][newJ] {
				if check(newI, newJ, k+1) {
					return true
				}
			}
		}
		return false
	}
	for i, row := range board {
		for j := range row {
			if check(i, j, 0) {
				return true
			}
		}
	}
	return false
}

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注