给定一个二维网格和一个单词,找出该单词是否存在于网格中。

单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

示例:

board =
[
['A','B','C','E'],
['S','F','C','S'],
['A','D','E','E']
] 给定 word = "ABCCED", 返回 true.
给定 word = "SEE", 返回 true.
给定 word = "ABCB", 返回 false.

https://leetcode-cn.com/problems/word-search/

深度优先遍历 DFS

原二维数组就像是一个迷宫,可以上下左右四个方向行走,我们以二维数组中每一个数都作为起点和给定字符串做匹配,

我们还需要一个和原数组等大小的 visited 数组,是 bool 型的,用来记录当前位置是否已经被访问过,因为题目要求一个 cell 只能被访问一次。

如果二维数组 board 的当前字符和目标字符串 word 对应的字符相等,则对其上下左右四个邻字符分别调用 DFS 的递归函数,只要有一个返回 true,那么就表示可以找到对应的字符串,否则就不能找到,具体看代码实现如下:

c++

class Solution {
public:
bool exist(vector<vector<char>>& board, string word) {
if (board.empty() || board[0].empty()) return false;
int m = board.size(), n = board[0].size();
vector<vector<bool>> visited(m, vector<bool>(n)); for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (search(board, word, 0, i, j, visited)) return true;
}
}
return false;
}
bool search(vector<vector<char>>& board, string word, int idx, int i, int j, vector<vector<bool>>& visited) {
if (idx == word.size()) return true;
int m = board.size(), n = board[0].size(); if (i < 0 || j < 0 || i >= m || j >= n || visited[i][j] || board[i][j] != word[idx]) return false; visited[i][j] = true;
bool res = search(board, word, idx + 1, i - 1, j, visited)
|| search(board, word, idx + 1, i + 1, j, visited)
|| search(board, word, idx + 1, i, j - 1, visited)
|| search(board, word, idx + 1, i, j + 1, visited);
visited[i][j] = false; return res;
}
};

java

public class Solution {

    private boolean[][] marked;
// x-1,y
// x,y-1 x,y x,y+1
// x+1,y
private int[][] direction = {{-1, 0}, {0, -1}, {0, 1}, {1, 0}};
private int m; // 盘面上有多少行
private int n; // 盘面上有多少列
private String word;
private char[][] board; public boolean exist(char[][] board, String word) {
m = board.length;
if (m == 0) {
return false;
}
n = board[0].length;
marked = new boolean[m][n];
this.word = word;
this.board = board; for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (dfs(i, j, 0)) {
return true;
}
}
}
return false;
} private boolean inArea(int x, int y) {
return x >= 0 && x < m && y >= 0 && y < n;
} private boolean dfs(int i, int j, int start) {
if (start == word.length() - 1) {
return board[i][j] == word.charAt(start);
}
if (board[i][j] == word.charAt(start)) {
marked[i][j] = true;
for (int k = 0; k < 4; k++) {
int newX = i + direction[k][0];
int newY = j + direction[k][1];
if (inArea(newX, newY) && !marked[newX][newY]) {
if (dfs(newX, newY, start + 1)) {
return true;
}
}
}
marked[i][j] = false;
}
return false;
}
}

python

from typing import List

class Solution:
# (x-1,y)
# (x,y-1) (x,y) (x,y+1)
# (x+1,y)
directions = [(0, -1), (-1, 0), (0, 1), (1, 0)] def exist(self, board: List[List[str]], word: str) -> bool:
m = len(board)
if m == 0:
return False
n = len(board[0]) marked = [[False for _ in range(n)] for _ in range(m)]
for i in range(m):
for j in range(n):
# 对每一个格子都从头开始搜索
if self.__search_word(board, word, 0, i, j, marked, m, n):
return True
return False def __search_word(self, board, word, index,
start_x, start_y, marked, m, n):
# 先写递归终止条件
if index == len(word) - 1:
return board[start_x][start_y] == word[index] # 中间匹配了,再继续搜索
if board[start_x][start_y] == word[index]:
# 先占住这个位置,搜索不成功的话,要释放掉
marked[start_x][start_y] = True
for direction in self.directions:
new_x = start_x + direction[0]
new_y = start_y + direction[1]
# 注意:如果这一次 search word 成功的话,就返回
if 0 <= new_x < m and 0 <= new_y < n and \
not marked[new_x][new_y] and \
self.__search_word(board, word,
index + 1,
new_x, new_y,
marked, m, n):
return True
marked[start_x][start_y] = False
return False

改进

我们还可以不用 visited 数组,直接对 board 数组进行修改,将其遍历过的位置改为井号,记得递归调用完后需要恢复之前的状态,参见代码如下:

c++

class Solution {
public:
bool exist(vector<vector<char>>& board, string word) {
if (board.empty() || board[0].empty()) return false;
int m = board.size(), n = board[0].size();
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (search(board, word, 0, i, j)) return true;
}
}
return false;
}
bool search(vector<vector<char>>& board, string word, int idx, int i, int j) {
if (idx == word.size()) return true;
int m = board.size(), n = board[0].size();
if (i < 0 || j < 0 || i >= m || j >= n || board[i][j] != word[idx]) return false;
char c = board[i][j];
board[i][j] = '#';
bool res = search(board, word, idx + 1, i - 1, j)
|| search(board, word, idx + 1, i + 1, j)
|| search(board, word, idx + 1, i, j - 1)
|| search(board, word, idx + 1, i, j + 1);
board[i][j] = c;
return res;
}
};

LeetCode——79. 单词搜索的更多相关文章

  1. Java实现 LeetCode 79 单词搜索

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

  2. Leetcode 79.单词搜索

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

  3. LeetCode 79.单词搜索 - JavaScript

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

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

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

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

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

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

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

  7. [LeetCode题解]79. 单词搜索

    题目描述 题目:79. 单词搜索 解题思路 遍历 首先找重复性,题目说给定单词是否存在于二维数组中,可以简化为从 (x, y) 走 n 步(n 表示单词长度),查看给定单词是否存在.然后再遍历二维数组 ...

  8. [leetcode] 212. 单词搜索 II(Java)

    212. 单词搜索 II 这leetcode的评判机绝对有问题!!同样的代码提交,有时却超时!害得我至少浪费两个小时来寻找更优的答案= =,其实第一次写完的代码就可以过了,靠!!!第207位做出来的 ...

  9. Leetcode 212.单词搜索II

    单词搜索II 给定一个二维网格 board 和一个字典中的单词列表 words,找出所有同时在二维网格和字典中出现的单词. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中"相邻&q ...

随机推荐

  1. 022、Java中boolean的用法

    01.代码如下: package TIANPAN; /** * 此处为文档注释 * * @author 田攀 微信382477247 */ public class TestDemo { public ...

  2. etcd入门

    简介 etcd是CoreOS团队于2013年6月发起的开源项目,它的目标是构建一个高可用的分布式键值(key-value)数据库. etcd内部采用raft协议作为一致性算法,基于Go语言实现. et ...

  3. SQL语句中为什么要用 where 1=1

    where 1=1; 这个条件始终为True,在不定数量查询条件情况下,1=1可以很方便的规范语句,1=1 是永恒成立的,意思无条件的,也就是说在SQL语句中有没有这个1=1都可以. 如:web界面查 ...

  4. pip制作离线安装包

    有的电脑无法连接外网(金融行业你懂的),上网下载包又下载不到 anaconda安装一个包(联网情况下)很简单 pip install python-docx 如何把python-docx做成离线包安装 ...

  5. REST接口

    全名是Representational State Transfer REST是设计风格而不是标准 建议将JSON格式作为标准响应格式 -------------------------------- ...

  6. Oracle SQL存储过程结构、异常处理示例

    -- 存储过程结结构. -- EXCeption不是存储过程必须部分,可以用作本存储过程的异常处理,但如果没有异常处理,出了异常将会终止程序 CREATE PROCEDURE procedure_na ...

  7. Tomcat添加SSL安全认证

    环境 Tomcat7.阿里SSL证书 server.xml <Connector port="443" protocol="org.apache.coyote.ht ...

  8. Bug 佛祖镇楼

    原文链接:https://www.cnblogs.com/xdp-gacl/p/4198935.html // _ooOoo_ // o8888888o // 88" . "88 ...

  9. 六十一、SAP中的逻辑运算与进制转换

    一.代码如下 二.16进制计算过程如下 三.计算结果为16进制的11,也就是10进制的17

  10. 哈希(hash)理解

    转载自https://www.cnblogs.com/mingaixin/p/4318837.html 一.什么是哈希?(一种更复杂的映射) Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就 ...