本文始发于个人公众号: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. Win10企业版远程桌面结合frp实现公网远程

    Win10企业版远程桌面结合frp实现公网远程 前言 由于经常下班后还要处理问题,但是又没有运维那么频繁,就不想天天背着电脑来回跑,刚开始用的teamviewer,后来被商业劝退了(就是不让用了,让买 ...

  2. Java学习之路【第一篇】:前言

    Java 语言概述 一.什么是Java语言 Java语言是美国Sun公司(Stanford University Network),在1995年推出的高级的编程语言.所谓编程语言,是计算机的语言,人们 ...

  3. nginx 搭建图片服务器(windows 下,linux 下原理应该一样)

    作者的心声:很多知道的.用过的东西,不写下来,下次还要百度查询,浪费时间和精力,故本次写下学习笔记,方便下次查阅. 题外话:如有读者通过我这篇博客解决了工作上的难题,可以给个评论,让我一起分享你的喜悦 ...

  4. hexo命令提示 hexo <command>

    所有的hexo命令执行后都会提示 hexo <command> 解决方法: 通过hexo init blog命令初始化一个博客后,应该cd /blog 转到博客目录

  5. Rocket - interrupts - Xbar

    https://mp.weixin.qq.com/s/icPGf4KdSOudwuNpLxdo7w 简单介绍Xbar的实现. 1. 简单介绍 IntXbar主要用于把上游多个中断源的中断组合在一起,然 ...

  6. Java实现 蓝桥杯 算法提高 成绩排序2

    试题 算法提高 成绩排序2 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 给出n个学生的成绩,将这些学生按成绩排序,排序规则:总分高的在前:总分相同,数学成绩高的在前:总分与数学相 ...

  7. Java GUI 窗体事件

    import java.awt.Frame; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; publi ...

  8. Java实现第九届蓝桥杯螺旋折线

    螺旋折线 题目描述 如图p1.pgn所示的螺旋折线经过平面上所有整点恰好一次. 对于整点(X, Y),我们定义它到原点的距离dis(X, Y)是从原点到(X, Y)的螺旋折线段的长度. 例如dis(0 ...

  9. TZOJ 公交车

    描述 公交车在一条笔直的道路(道路宽度忽略,设为X轴)上行驶,按顺序路上有若干个站点(X坐标值),crq的家也在道路旁某个位置h(X坐标值),现在crq想知道哪个站点下车离家最近. 输入 输入数据的第 ...

  10. 运用Navicat for MySQL进行MSSQL数据转移MYSQL

    当前不同数据库进行数据转移已经不是一件麻烦事情,特别是有很多很方便的工具,而最近我在搜集各种数据时候,也需要进行大量的数据转移,并且数据库和所转移的数据库表都不同,这次给大家介绍个最简单的方法,就是使 ...