LeetCode79 单词搜索 Python3

原题链接:点击

给定一个二维网格和一个单词,找出该单词是否存在于网格中。

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

示例:

board =
[
  ['A','B','C','E'],
  ['S','F','C','S'],
  ['A','D','E','E']
]

给定 word = "ABCCED", 返回 true.
给定 word = "SEE", 返回 true.
给定 word = "ABCB", 返回 false.

这其实是深度优先搜索(DFS)+回溯(BT)的一种常见题型。很明显,我们首先要找到初始搜索位置,然后根据这个搜索位置上、下、左、右依次查找是否匹配下一个字符,在搜索的过程中还要注意边界条件的约束,一旦找到匹配成功的字符,记录它确保下次不被访问,并继而据该字符进行同样的搜索,直到搜索到最后一个字符,返回结果;这是顺利的情形,但实际上我们会有匹配失败的情形出现,即据该字符的四周无法找到一个合适的字符,那么就应该回溯,并消除该字符被访问过的记录。

其实说到底就是标准的回溯思想,消化一下不难理解代码:

# 上下左右
directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
def exist(board, word):
	m = len(board)
	if m == 0:
		return False
	n = len(board[0])
	# 通过找到首字母进行切入搜索
	firstLetter = word[0]
	for i in range(m):
		for j in range(n):
			if firstLetter == board[i][j]:
				# 从首字符匹配的那个开始搜索
				# 如果匹配成功 就可以直接返回true
				# visited数组记录访问过的元素
				visited = set()
				visited.add((i, j))
				if dfs(i, j, board, index, word, m, n, visited):
					return True
	return False
	# 递归函数
	def dfs(x, y, board, index, word, m, n, visited): 
		# DFS搜索
		# index表示当前匹配到的word索引
		if index == len(word)-1:
			return word[index] == board[x][y]
		for d in directions:
			curX, curY = x + d[0], y + d[1]
			# 约束条件 没被访问 且 下一个字符匹配成功
			# 我们就返回 true
			if 0 <= curX <= m-1 and <= curY <= n-1 and 
			(curX, curY) not in visited and dfs(curX, curY, board, index+1, word, m, n, visited):
				return True
			# 回溯
			visited.remove((x, y))
		return False

代码理解起来不难,就是函数传参有点多…并且还另外开辟了集合用于保存访问过的变量,其中搜索过程也需要一定的时间复杂度。对此,我们还可以写出这种易懂的形式:

def exist(board, word):
	m = len(board)
	if m == 0:
		return False
	n = len(board[0])
	# 通过一个布尔量来记录是否成功找到字符串
	self.flag = False
	for i in range(m):
		for j in range(n):
			if word[0]== board[i][j]:
				dfs(i, j, 0, m, n, board, word)
	return self.flag
	
	def dfs(x, y, index, m, n, board, word): 
		# DFS搜索
		# 并利用 board 来记录状态
		# index表示当前匹配到的word索引
		# 函数递归返回的情形
		# 1.边界条件
		# 2.查找索引大于查找字符串长度
		# 3.匹配失败
		# 4.已经找到
		if x < 0 or y < 0 or x >= m or y >= n or index >= len(word) or board[x][y] != word[index] or self.flag:
			return
		if index == len(word)-1:
			self.flag = True
		# 递归+回溯模板
		oldValue = board[x][y]
		board[x][y] = ' '
		dfs(x+1, y, index+1, m, n, board, word)
		dfs(x, y+1, index+1, m, n, board, word)
		dfs(x-1, y, index+1, m, n, board, word)
		dfs(x, y-1, index+1, m, n, board, word)
		board[x][y] = oldValue

这里有意思的还有一点,就是递归函数中参数的传递形式问题。可以尝试分别使用值传递和引用传递的方式运行程序,从结果上来看似乎引用传递的效率会更好,具体的原因不是很清楚,想必和递归运行时栈的开辟与参数变量的保存有关系,似乎存在参数在函数内没有发生改变时,使用引用传递会提升效率…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Key Board

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值