[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)
题目描述 给定一个二维网格和一个单词,找出该单词是否存在于网格中. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格.同一个单元格内的字母不允许被 ...
随机推荐
- Java 程序员生产神器 IDEA 的常用快捷键、插件及设置
对于 Java 程序员来说,使用 IDEA 集成环境是最称手的.优点不多讲,用过的人都知道.IDEA 虽好,但为了充分利用 IDEA 的优势,我分享一下我常用快捷键.插件和设置. 常用快捷键 Ctrl ...
- javascript 简单、繁杂类型、栈、堆笔记
简单数据类型 值类型:在存储变量中的是值本身 简单数据类型 null返回的是空的对象 string,number,Boolean,undefined,null 繁杂数据类型 ...
- Spring Cloud 之分布式配置基础应用
分布式配置基础应用 配置中心服务 spring-config-server pom.xml <?xml version="1.0" encoding="UTF-8& ...
- 《闲扯Redis十》Redis 跳跃表的结构实现
一.前言 Redis 提供了5种数据类型:String(字符串).Hash(哈希).List(列表).Set(集合).Zset(有序集合),理解每种数据类型的特点对于redis的开发和运维非常重要. ...
- s2-001漏洞复现
struts2-001 该漏洞因为用户提交表单数据并且验证失败时,后端会将用户之前提交的参数值使用 OGNL 表达式 %{value} 进行解析,然后重新填充到对应的表单数据中.例如注册或登录页面,提 ...
- c cpp编程用到的系统边角与其拾遗
拾遗 Q:unix编程怎么查一个函数在哪个头文件中 A: 可以用诸如 man 3 printf Q: man后面接个数字什么意思,如man 3 printf A:如下 man man中的引用 下表显示 ...
- 【SDOI2009】 HH的项链 - 莫队
题目描述 HH 有一串由各种漂亮的贝壳组成的项链.HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH 不断地收集新的贝壳,因此,他的项链变得越来越长. ...
- [源码解析] 当 Java Stream 遇见 Flink
[源码解析] 当 Java Stream 遇见 Flink 目录 [源码解析] 当 Java Stream 遇见 Flink 0x00 摘要 0x01 领域 1.1 Flink 1.2 Java St ...
- 数据恢复----重组raid5解析
重组Raid5 第一步:判断RAID5条带大小 利用winhex同时打开6个物理镜像每块成员盘中的$MFT文件记录(16进制搜索“46494c45”),并且保证找到的文件记录在每块物理盘的同一扇区(在 ...
- java基础-02:编译型和解释型
Java程序运行机制: Java语言的编译-->解释-->运行过程 1.编译型语言:程序在执行之前需要一个专门的编译过程,把程序编译成为机器语言的文件,运行时不需要重新翻译,直接使用编译的 ...