本文始发于个人公众号:TechFlow,原创不易,求个关注

今天是LeetCode专题第48篇文章,我们一起来看看LeetCode当中的第79题,搜索单词(Word Search)。

这一题官方给的难度是Medium,通过率是34.5%,点赞3488,反对170。单从这份数据上来看,这题的质量很高,并且难度比之前的题目稍稍大一些。我个人觉得通过率是比官方给的题目难得更有参考意义的指标,10%到20%可以认为是较难的题,30%左右是偏难的题。50%是偏易题,所以如果看到某题标着Hard,但是通过率有50%,要么说明题目很水,要么说明数据很水,总有一点很水。

题意

废话不多说,我们来看题意:

这题的题面挺有意思,给定一个二维的字符型数组,以及一个字符串,要求我们来判断能否在二维数组当中找到一条路径,使得这条路径上的字符连成的字符串和给定的字符串相等?

样例

board =
[
['A','B','C','E'],
['S','F','C','S'],
['A','D','E','E']
] Given word = "ABCCED", return true.
Given word = "SEE", return true.
Given word = "ABCB", return false.

比如第一个字符串ABCCED,我们可以在数组当中找到这样一条路径:

题解

不知道大家看到题面和这个样例有什么样的感觉,如果你刷过许多题,经常思考的话,我想应该不难发现,这道题的本质其实和走迷宫问题是一样的。

我们拿到的这个二维的字符型数组就是一个迷宫, 我们是要在这个迷宫当中找一条“出路”。不过我们的目的不是找到终点,而是找到一条符合题意的路径。在走迷宫问题当中,迷宫中不是每一个点都可以走的,同样在当前问题当中,也不是每一个点都符合字符串的要求的。这两个问题虽然题面看起来大相径庭,但是核心的本质是一样的。

我们来回忆一下,走迷宫问题应该怎么解决?

这个答案应该已经非常确定了,当然是搜索算法。我们需要搜索解可能存在的空间去寻找存在的解,也就是说我们面临的是一个解是否存在的问题,要么找到解,要么遍历完所有的可能性发现解不存在。确定了是搜索算法之后,剩下的就简单了,我们只有两个选项,深度优先或者是广度优先。

理论上来说,一般判断解的存在性问题,我们使用广度优先搜索更多,因为一般来说它可以更快地找到解。但是本题当中有一个小问题是,广度优先搜索需要在队列当中存储中间状态,需要记录地图上行走过的信息,每有一个状态就需要存储一份地图信息,这会带来比较大的内存开销,同样存储的过程也会带来计算开销,在这道题当中,这是不可以接受的。拷贝状态带来的空间消耗还是小事,关键是拷贝带来的时间开销,就足够让这题超时了。所以我们别无选择,只能深度优先。

明确了算法之后,只剩下了最后一个问题,在这个走迷宫问题当中,我们怎么找到迷宫的入口呢?因为题目当中并没有规定我们起始点的位置,这也不难解决,我们遍历二维的字符数组,和字符串开头相匹配的位置都可以作为迷宫的入口。

最后,我们来看代码,并没有什么技术含量,只是简单的回溯法而已。

class Solution:
def exist(self, board: List[List[str]], word: str) -> bool:
fx = [[0, 1], [0, -1], [1, 0], [-1, 0]]
def dfs(x, y, l):
if l == len(word):
return True
for i in range(4):
nx = x + fx[i][0]
ny = y + fx[i][1]
# 出界或者是走过的时候,跳过
if nx < 0 or nx == n or ny < 0 or ny == m or visited[nx][ny]:
continue
if board[nx][ny] == word[l]:
visited[nx][ny] = 1
if dfs(nx, ny, l+1):
return True
visited[nx][ny] = 0
return False n = len(board)
if n == 0:
return False
m = len(board[0])
if m == 0:
return False visited = [[0 for i in range(m)] for j in range(n)] for i in range(n):
for j in range(m):
# 找到合法的起点
if board[i][j] == word[0]:
visited = [[0 for _ in range(m)] for _ in range(n)]
visited[i][j] = 1
if dfs(i, j, 1):
return True return False

总结

如果能够想通回溯法,并且对于回溯法的实现足够熟悉,那么这题的难度是不大的。实际上至今为止,我们一路刷来,已经做了好几道回溯法的问题了,我想对你们来说,回溯法的问题应该已经小菜一碟了。

相比于回溯法来说,我觉得更重要的是我们能够通过分析想清楚,为什么广度优先搜索不行,底层核心的本质原因是什么。这个思考的过程往往比最后的结论来得重要。

如果喜欢本文,可以的话,请点个关注,给我一点鼓励,也方便获取更多文章。

本文使用 mdnice 排版

LeetCode 79,这道走迷宫问题为什么不能用宽搜呢?的更多相关文章

  1. 老鼠走迷宫II

    转自:http://blog.csdn.net/holymaple/article/details/8636234 由于迷宫的设计,老鼠走迷宫的入口至出口路径可能不止一条,如何求出所有的路径呢? 解法 ...

  2. 老鼠走迷宫I

    转自:http://blog.csdn.net/holymaple/article/details/8582517 说明:老鼠走迷宫是递回求解的基本提醒,我们在二维阵列中使用2来表示迷宫墙壁,使用1来 ...

  3. C语言动态走迷宫

    曾经用C语言做过的动态走迷宫程序,先分享代码如下: 代码如下: //头文件 #include<stdio.h> #include<windows.h>//Sleep(500)函 ...

  4. sdut 2449走迷宫【最简单的dfs应用】

    走迷宫 Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_ 题目描述 一个由n * m 个格子组成的迷宫,起点是(1, 1), 终点是(n, m) ...

  5. 洛谷P1238 走迷宫

    洛谷1238 走迷宫 题目描述 有一个m*n格的迷宫(表示有m行.n列),其中有可走的也有不可走的,如果用1表示可以走,0表示不可以走,文件读入这m*n个数据和起始点.结束点(起始点和结束点都是用两个 ...

  6. BZOJ 2707: [SDOI2012]走迷宫( tarjan + 高斯消元 )

    数据范围太大不能直接高斯消元, tarjan缩点然后按拓扑逆序对每个强连通分量高斯消元就可以了. E(u) = 1 + Σ E(v) / degree(u) 对拍时发现网上2个程序的INF判断和我不一 ...

  7. NYOJ306 走迷宫(dfs+二分搜索)

    题目描写叙述 http://acm.nyist.net/JudgeOnline/problem.php?pid=306 Dr.Kong设计的机器人卡多非常爱玩.它经常偷偷跑出实验室,在某个游乐场玩之不 ...

  8. Problem A: 走迷宫问题

    Problem A: 走迷宫问题Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 9 Solved: 3[Submit][Status][Web Board] ...

  9. BZOJ 2707: [SDOI2012]走迷宫 [高斯消元 scc缩点]

    2707: [SDOI2012]走迷宫 题意:求s走到t期望步数,\(n \le 10^4\),保证\(|SCC| \le 100\) 求scc缩点,每个scc高斯消元,scc之间直接DP 注意每次清 ...

随机推荐

  1. html2canvas.js插件截图空白问题

    发现使用 html2canvas.js插件截图保存在前端很方便.学习过程中预计问题. 截图出现空白和截图不全. 问题原因: html2canvas.js插件截图是基于body标签的,如果body存在滚 ...

  2. python常见面试题讲解(十)数字颠倒

    题目描述 描述: 输入一个整数,将这个整数以字符串的形式逆序输出 程序不考虑负数的情况,若数字含有0,则逆序形式也含有0,如输入为100,则输出为001 输入描述: 输入一个int整数 输出描述: 将 ...

  3. uni-app之uni.showToast()image路径问题

    uni-app的API中,showToast的icon值只有success,loading,none三种显示,失败没有图标.如果失败时需要显示图标,就要用到自定义图标 image 了. uni.sho ...

  4. FreeRTOS-为什么关中断之后切换进程?

    https://mp.weixin.qq.com/s/S5HBH3RTo0B2irr8sGwDdw   一. 基本问题   FreeRTOS会在关键区即taskENTER_CRITICAL()和tas ...

  5. jchdl - GSL实例 - MulC2(有符号数的乘法)

      这里的实现,先把符号位取出来,使用两个正数相乘,然后在把符号加到乘积上.   参考链接 https://github.com/wjcdx/jchdl/blob/master/src/org/jch ...

  6. Java实现 LeetCode 638 大礼包(阅读理解题,DFS)

    638. 大礼包 在LeetCode商店中, 有许多在售的物品. 然而,也有一些大礼包,每个大礼包以优惠的价格捆绑销售一组物品. 现给定每个物品的价格,每个大礼包包含物品的清单,以及待购物品清单.请输 ...

  7. Java实现 蓝桥杯VIP 基础练习 回形取数

    问题描述 回形取数就是沿矩阵的边取数,若当前方向上无数可取或已经取过,则左转90度.一开始位于矩阵左上角,方向向下. 输入格式 输入第一行是两个不超过200的正整数m, n,表示矩阵的行和列.接下来m ...

  8. Java实现 蓝桥杯VIP 算法训练 会议中心

    算法训练 会议中心 时间限制:2.0s 内存限制:512.0MB 会议中心 Siruseri政府建造了一座新的会议中心.许多公司对租借会议中心的会堂很感兴趣,他们希望能够在里面举行会议. 对于一个客户 ...

  9. Java中那些烦人的位运算(&,|...)

    & 和 && 相同点: 都表示"与"操作.这里的"与"和数学中的"与或非"中的"与"意义相同,都 ...

  10. Java实现 LeetCode 81 搜索旋转排序数组 II(二)

    81. 搜索旋转排序数组 II 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,0,1,2,2,5,6] 可能变为 [2,5,6,0,0,1,2] ). 编写一个函数来判 ...