题目描述

题目: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. 单词搜索的更多相关文章

  1. Leetcode题目79.单词搜索(回溯+DFS-中等)

    题目描述: 给定一个二维网格和一个单词,找出该单词是否存在于网格中. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格.同一个单元格内的字母不允许 ...

  2. Leetcode之回溯法专题-79. 单词搜索(Word Search)

    Leetcode之回溯法专题-79. 单词搜索(Word Search) 给定一个二维网格和一个单词,找出该单词是否存在于网格中. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元 ...

  3. Java实现 LeetCode 79 单词搜索

    79. 单词搜索 给定一个二维网格和一个单词,找出该单词是否存在于网格中. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中"相邻"单元格是那些水平相邻或垂直相邻的单元格. ...

  4. Leetcode 79.单词搜索

    单词搜索 给定一个二维网格和一个单词,找出该单词是否存在于网格中. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中"相邻"单元格是那些水平相邻或垂直相邻的单元格.同一个单 ...

  5. [LeetCode] 79. 单词搜索(DFS,回溯)

    题目 给定一个二维网格和一个单词,找出该单词是否存在于网格中. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中"相邻"单元格是那些水平相邻或垂直相邻的单元格.同一个单元格 ...

  6. LeetCode 79.单词搜索 - JavaScript

    题目描述:给定一个二维网格和一个单词,找出该单词是否存在于网格中. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中"相邻"单元格是那些水平相邻或垂直相邻的单元格.同一个单 ...

  7. LeetCode——79. 单词搜索

    给定一个二维网格和一个单词,找出该单词是否存在于网格中. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中"相邻"单元格是那些水平相邻或垂直相邻的单元格.同一个单元格内的字 ...

  8. leetcode刷题-79单词搜索

    题目 给定一个二维网格和一个单词,找出该单词是否存在于网格中. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格.同一个单元格内的字母不允许被重复 ...

  9. LeetCode 79. 单词搜索(Word Search)

    题目描述 给定一个二维网格和一个单词,找出该单词是否存在于网格中. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格.同一个单元格内的字母不允许被 ...

随机推荐

  1. DCGAN实现

    DCGAN实现 代码 dcgan.py #!/usr/bin/env python # -*- coding: utf-8 -*- import os import math import argpa ...

  2. Nginx MogileFS 配置

    配置好MogileFS, 见mogilefs的安装与配置随笔 下载nginx.1.10.3.tar.gz, nginx_mogilefs_module.1.0.4.tar.gz 编译安装 将连个tar ...

  3. 朴素贝叶斯算法java实现(多项式模型)

    网上有很多对朴素贝叶斯算法的说明的文章,在对算法实现前,参考了一下几篇文章: NLP系列(2)_用朴素贝叶斯进行文本分类(上) NLP系列(3)_用朴素贝叶斯进行文本分类(下) 带你搞懂朴素贝叶斯分类 ...

  4. [转]解决The requested resource is not available的方法

    此博文为转载博文,首先感谢原作者 HTTP Status 404(The requested resource is not available)异常主要是路径错误或拼写错误造成的,请按以下步骤逐一排 ...

  5. 2020-05-14:实现分布式Session的过程是怎样的?

    福哥答案2020-05-14: 此答案来自群员:分布式session ,最开始起源是双机热备,当时php1和php2为了共享session,一开始采用samba/nfs,后来php有了插件以后就扔当时 ...

  6. BLE GAP 协议和 GATT 协议

    BLE GAP 协议和 GATT 协议 最近要打算学习 Blufi 协议进行蓝牙配置,其中必然使用 GAP 协议和 GATT 协议,于是进行重新学习一番. BLE 是一个 Bluetooth SIG ...

  7. Goland 生成可执行文件

    Goland通过调用go build 生成可执行文件. 默认Goland是可以执行程序,但你找不到可执行文件. 你需要自定义配置文件. 创建go build配置文件 Run kind 选Directo ...

  8. Spark从入门到放弃---RDD

    什么是Spark? 关于Spark具体的定义,大家可以去阅读官网或者百度关于Spark的词条,在此不再赘述.从一个野生程序猿的角度去理解,作为大数据时代的一个准王者,Spark是一款主流的高性能分布式 ...

  9. Could not create an acl object: Role '16'

    解决方案: (1) 用rm命令一个一个的清除var/cache, var/page_cache, var/di, generated/文件夹下的所有文件 (2) run setup:upgradeco ...

  10. oracle进行一对多关联查询的时候,获取副表(也就是多条记录的那张表)的最新一条记录进行关联,如何获取多条记录最新一条呢?

    例如以下场景: 一条新闻对应多条审核记录,用户想知道这条新闻走到哪一步审核了. 使用:select * from (select b.*,(ROW_NUMBER() OVER (PARTITION B ...