[LeetCode题解]79. 单词搜索
题目描述

题目:79. 单词搜索
解题思路
遍历
首先找重复性,题目说给定单词是否存在于二维数组中,可以简化为从 (x, y) 走 n 步(n 表示单词长度),查看给定单词是否存在。然后再遍历二维数组里的所有点,看是否存在给定单词。
func exist(board [][]byte, word string) bool {
for x:=0;x<n;x++ {
for y:=0;y<m;y++ {
if dfs(x, y, 0) {
return true
}
}
}
return false
}
回溯
从 (x, y) 走 n 步,每一步都可以从上下左右四个方向“试探步”,直到走完 n 步,然后再比较“走过的路径” 和给定单词是否相等。
func backtrack(x int, y int, index int, s *[]byte) {
// 终止条件:走完 n 步
if index == len(word) {
return string(s) == word
}
if !visited[x][y] {
visited[x][y] = true
s = append(s, board[x][y])
for i:=0;i<direction;i++ {
newX, newY := x+direction[i][0], y+direction[i][1]
if backtrack(newX, newY, index+1) {
return true
}
}
s = s[:len(s)]
visited[x][y] = false
}
return false
}
此代码存在问题,没有考虑边界的问题,当向上下左右移动时,不能超过边界,因此代码调整为:
func backtrack(x int, y int, index int, s *[]byte) {
// 终止条件:走完 n 步
if index == len(word) {
return string(s) == word
}
if !visited[x][y] {
visited[x][y] = true
s = append(s, board[x][y])
for i:=0;i<direction;i++ {
newX, newY := x+direction[i][0], y+direction[i][1]
if inArea(newX, newY) && backtrack(newX, newY, index+1) {
return true
}
}
s = s[:len(s)]
visited[x][y] = false
}
return false
}
func inArea(x int, y int) bool {
return x < n && x >= 0 && y < m && y >= 0
}
剪枝
上面的代码可以进一步优化,在回溯过程中,可以预先判断结果,假如走到第 i 步时,此时的字符与给定单词的第 i 位字符不相等,则可以剪掉后续的比较,即剪掉分支。
注:回溯、dfs 本质上是递归,函数调用的过程会生成一颗递归树。
func backtrack(x int, y int, index int) bool {
if index == len(word)-1 {
return board[x][y] == word[index]
}
if board[x][y] == word[index] {
visited[x][y] = true
// 遍历四个方向
for i := 0; i < len(direction); i++ {
newX, newY := x+direction[i][0], y+direction[i][1]
if inArea(newX, newY) && !visited[newX][newY] {
if backtrack(newX, newY, index+1) {
return true
}
}
}
visited[x][y] = false
}
return false
}
func inArea(x int, y int) bool {
return x < n && x >= 0 && y < m && y >= 0
}
代码实现
var direction = [][]int{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}
var visited [][]bool
var n, m int
func exist(board [][]byte, word string) bool {
n = len(board)
if n == 0 {
return false
}
m = len(board[0])
if m == 0 {
return false
}
visited = make([][]bool, n)
for i := 0; i < n; i++ {
visited[i] = make([]bool, m)
}
for x := 0; x < n; x++ {
for y := 0; y < m; y++ {
if backtrack(board, word, 0, x, y) {
return true
}
}
}
return false
}
func backtrack(board [][]byte, word string, index int, x int, y int) bool {
if index == len(word)-1 {
return board[x][y] == word[index]
}
if board[x][y] == word[index] {
visited[x][y] = true
// 遍历四个方向
for i := 0; i < len(direction); i++ {
newX, newY := x+direction[i][0], y+direction[i][1]
if inArea(newX, newY) && !visited[newX][newY] {
if backtrack(board, word, index+1, newX, newY) {
return true
}
}
}
visited[x][y] = false
}
return false
}
func inArea(x int, y int) bool {
return x < n && x >= 0 && y < m && y >= 0
}
复杂度分析:
- 时间复杂度:O(n * m * L),其中 n, m, L 分别表示二维数组的行、列和给定单词的长度。
- 最好情况,遍历二维数组第一个元素,且走一次就找到。
- 最坏情况,要遍历到二维数组的最后一个元素,并且各个方向都走完后,没找到结果。
- 空间复杂度:O(n * m),其中 n, m 分别表示二维数组的行、列。只需要一个二维数组记录是否访问过元素。
总结
- 对于类似排列、组合的问题,第一时间要想到可以使用dfs、回溯来解决。
- 一般来说,回溯和剪枝是一起使用的,在优化时间复杂度时,记得考虑剪枝。
[LeetCode题解]79. 单词搜索的更多相关文章
- Leetcode题目79.单词搜索(回溯+DFS-中等)
题目描述: 给定一个二维网格和一个单词,找出该单词是否存在于网格中. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格.同一个单元格内的字母不允许 ...
- Leetcode之回溯法专题-79. 单词搜索(Word Search)
Leetcode之回溯法专题-79. 单词搜索(Word Search) 给定一个二维网格和一个单词,找出该单词是否存在于网格中. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元 ...
- Java实现 LeetCode 79 单词搜索
79. 单词搜索 给定一个二维网格和一个单词,找出该单词是否存在于网格中. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中"相邻"单元格是那些水平相邻或垂直相邻的单元格. ...
- Leetcode 79.单词搜索
单词搜索 给定一个二维网格和一个单词,找出该单词是否存在于网格中. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中"相邻"单元格是那些水平相邻或垂直相邻的单元格.同一个单 ...
- [LeetCode] 79. 单词搜索(DFS,回溯)
题目 给定一个二维网格和一个单词,找出该单词是否存在于网格中. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中"相邻"单元格是那些水平相邻或垂直相邻的单元格.同一个单元格 ...
- LeetCode 79.单词搜索 - JavaScript
题目描述:给定一个二维网格和一个单词,找出该单词是否存在于网格中. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中"相邻"单元格是那些水平相邻或垂直相邻的单元格.同一个单 ...
- LeetCode——79. 单词搜索
给定一个二维网格和一个单词,找出该单词是否存在于网格中. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中"相邻"单元格是那些水平相邻或垂直相邻的单元格.同一个单元格内的字 ...
- leetcode刷题-79单词搜索
题目 给定一个二维网格和一个单词,找出该单词是否存在于网格中. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格.同一个单元格内的字母不允许被重复 ...
- LeetCode 79. 单词搜索(Word Search)
题目描述 给定一个二维网格和一个单词,找出该单词是否存在于网格中. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格.同一个单元格内的字母不允许被 ...
随机推荐
- Docker初探之运行RabbitMQ消息队列服务
我们平时在使用RabbitMQ是基于Windows操作系统的,在使用前需要安装Er-Lang和RabbitMQ服务程序,如果版本不对RabbitMQ就启动失败,安装流程也比较麻烦. 但如果在Docke ...
- SCOI2020迷惑记
睡了个好觉还是很困但没咋吃饭就出门了. 到了之后随便跟认得到的人扯了两句就进去了. 结果让我们站在外面等... 然后通知说不能自带水和吃的那我这个中午没吃饭的咋整啊. 马上啃了半块巧克力就进了考场,然 ...
- NoisyStudent:
- C#算法设计查找篇之05-二叉树查找
二叉树查找(Binary Tree Search) 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/706 访问. 二叉排 ...
- CPF 入门教程 - 数据绑定和命令绑定(二)
CPF netcore跨平台UI框架 系列教程 CPF 入门教程(一) CPF 入门教程 - 数据绑定和命令绑定(二) 数据绑定和Wpf类似,支持双向绑定.数据绑定和命令绑定是UI和业务逻辑分离的基础 ...
- 【算法•日更•第二十七期】基础python
▎前言 看到这个题目,你一定会很好奇,为什么学打NOIP的要学习python?其实python对我们是很有用的! NOIP虽然不支持使用python提交代码,但是在NOILinux上天生自带pytho ...
- Docker: docker pull, wget, curl, git clone 等如何更快?
1) Docker 配置 1.1) daemon.json 配置镜像 路径: /etc/docker/daemon.json 文档: Config Daemon registry-mirrors 设定 ...
- python列表的增删改查和嵌套
列表 python常用的数据类型 可承载任意的数据类型 列表是有序的,可索引.切片(步长) 列表的创建 list1 = [1, 2, 'whll'] #1. list2 = list() #2. #3 ...
- 修改linux 动态ip为静态ip
vi /etc/sysconfig/network-scripts/ifcfg-ens33 BOOTPROTO=static 设置网卡引导协议为 静态 ONBOOT=yes 网卡开机自启动 配置[IP ...
- java+opencv人脸识别程序2.0
由于第一次写的太粗糙了,所以又修改了一下,详细的更改如下: @ 目录 更改 窗口问题 识别问题 相似度对比 仍然存在的问题 人脸信息显示 图片质量 更改 优化了一下界面风格 窗口问题 原来是在主界面外 ...