12. 矩阵中的路径


comments: true
difficulty: 中等
edit_url: https://github.com/doocs/leetcode/edit/main/lcof/%E9%9D%A2%E8%AF%95%E9%A2%9812.%20%E7%9F%A9%E9%98%B5%E4%B8%AD%E7%9A%84%E8%B7%AF%E5%BE%84/README.md

面试题 12. 矩阵中的路径

题目描述

给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false

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

例如,在下面的 3×4 的矩阵中包含单词 "ABCCED"(单词中的字母已标出)。

示例 1:

输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
输出:true

示例 2:

输入:board = [["a","b"],["c","d"]], word = "abcd"
输出:false

提示:

  • 1 <= board.length <= 200
  • 1 <= board[i].length <= 200
  • boardword 仅由大小写英文字母组成

注意:本题与主站 79 题相同:https://leetcode.cn/problems/word-search/

解法

方法一:枚举 + DFS

我们可以枚举矩阵的每个位置 ( i , j ) (i, j) (i,j),以该位置为起点,采用深度优先搜索的方法寻找字符串 word 的路径。如果找到了一条路径,即可返回 true,否则在枚举完所有的位置后,返回 false

那么问题的转换为如何采用深度优先搜索的方法寻找字符串 word 的路径。我们可以设计一个函数 d f s ( i , j , k ) dfs(i, j, k) dfs(i,j,k),表示从位置 ( i , j ) (i, j) (i,j) 开始,且当前将要匹配的字符为 word[k] 的情况下,是否能够找到字符串 word 的路径。如果能找到,返回 true,否则返回 false

函数 d f s ( i , j , k ) dfs(i, j, k) dfs(i,j,k) 的执行流程如下:

  • 如果当前字符 word[k] 已经匹配到字符串 word 的末尾,说明已经找到了字符串 word 的路径,返回 true
  • 如果当前位置 ( i , j ) (i, j) (i,j) 超出矩阵边界,或者当前位置的字符与 word[k] 不同,说明当前位置不在字符串 word 的路径上,返回 false
  • 否则,我们将当前位置的字符标记为已访问(防止重复搜索),然后分别向当前位置的上、下、左、右四个方向继续匹配字符 word[k + 1],只要有一条路径能够匹配到字符串 word 的路径,就说明能够找到字符串 word 的路径,返回 true在回溯时,我们要将当前位置的字符还原为未访问过的状态。

时间复杂度 O ( m × n × 3 k ) O(m \times n \times 3^k) O(m×n×3k),空间复杂度 O ( m × n ) O(m \times n) O(m×n)。其中 m m m n n n 分别为矩阵的行数和列数,而 k k k 为字符串 word 的长度。我们需要枚举矩阵中的每个位置,然后对于每个位置,我们最多需要搜索三个方向。

a = pairwise(“abcdefg”) #获取连续重叠对
#a输出为"ab"bc"cd"de"ef"fg"

Python3
class Solution:def exist(self, board: List[List[str]], word: str) -> bool:def dfs(i, j, k):if k == len(word):return Trueif i < 0 or i >= m or j < 0 or j >= n or board[i][j] != word[k]:return Falseboard[i][j] = "" # 在递的过程中,标记已访问的方式,从而不会遍历到dirs = (-1, 0, 1, 0, -1)ans = any(dfs(i + a, j + b, k + 1) for a, b in pairwise(dirs))board[i][j] = word[k] #在归(回溯)的过程中,还原之前的状态return ansm, n = len(board), len(board[0])return any(dfs(i, j, 0) for i in range(m) for j in range(n))
Java
class Solution {private char[][] board;private String word;private int m;private int n;public boolean exist(char[][] board, String word) {m = board.length;n = board[0].length;this.board = board;this.word = word;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 dfs(int i, int j, int k) {if (k == word.length()) {return true;}if (i < 0 || i >= m || j < 0 || j >= n || word.charAt(k) != board[i][j]) {return false;}board[i][j] = ' ';int[] dirs = {-1, 0, 1, 0, -1};boolean ans = false;for (int l = 0; l < 4; ++l) {ans = ans || dfs(i + dirs[l], j + dirs[l + 1], k + 1);}board[i][j] = word.charAt(k);return ans;}
}
C++
class Solution {
public:bool exist(vector<vector<char>>& board, string word) {int m = board.size(), n = board[0].size();int dirs[5] = {-1, 0, 1, 0, -1};function<bool(int, int, int)> dfs = [&](int i, int j, int k) -> bool {if (k == word.size()) {return true;}if (i < 0 || i >= m || j < 0 || j >= n || board[i][j] != word[k]) {return false;}board[i][j] = '.';bool ans = 0;for (int l = 0; l < 4; ++l) {ans |= dfs(i + dirs[l], j + dirs[l + 1], k + 1);}board[i][j] = word[k];return ans;};for (int i = 0; i < m; ++i) {for (int j = 0; j < n; ++j) {if (dfs(i, j, 0)) {return true;}}}return false;}
};
Go
func exist(board [][]byte, word string) bool {m, n := len(board), len(board[0])var dfs func(i, j, k int) booldfs = func(i, j, k int) bool {if k == len(word) {return true}if i < 0 || i >= m || j < 0 || j >= n || board[i][j] != word[k] {return false}board[i][j] = ' 'dirs := []int{-1, 0, 1, 0, -1}ans := falsefor l := 0; l < 4; l++ {ans = ans || dfs(i+dirs[l], j+dirs[l+1], k+1)}board[i][j] = word[k]return ans}for i := 0; i < m; i++ {for j := 0; j < n; j++ {if dfs(i, j, 0) {return true}}}return false
}
TypeScript
function exist(board: string[][], word: string): boolean {const m = board.length;const n = board[0].length;const dfs = (i: number, j: number, k: number) => {if ((board[i] ?? [])[j] !== word[k]) {return false;}if (++k === word.length) {return true;}const temp = board[i][j];board[i][j] = ' ';if (dfs(i + 1, j, k) || dfs(i, j + 1, k) || dfs(i - 1, j, k) || dfs(i, j - 1, k)) {return true;}board[i][j] = temp;return false;};for (let i = 0; i < m; i++) {for (let j = 0; j < n; j++) {if (dfs(i, j, 0)) {return true;}}}return false;
}
Rust
impl Solution {fn dfs(board: &mut Vec<Vec<char>>,chars: &Vec<char>,i: usize,j: usize,mut k: usize,) -> bool {if board[i][j] != chars[k] {return false;}k += 1;if k == chars.len() {return true;}let temp = board[i][j];board[i][j] = ' ';if (i != 0 && Self::dfs(board, chars, i - 1, j, k))|| (j != 0 && Self::dfs(board, chars, i, j - 1, k))|| (i != board.len() - 1 && Self::dfs(board, chars, i + 1, j, k))|| (j != board[0].len() - 1 && Self::dfs(board, chars, i, j + 1, k)){return true;}board[i][j] = temp;false}pub fn exist(mut board: Vec<Vec<char>>, word: String) -> bool {let m = board.len();let n = board[0].len();let chars = word.chars().collect::<Vec<char>>();for i in 0..m {for j in 0..n {if Self::dfs(&mut board, &chars, i, j, 0) {return true;}}}false}
}
JavaScript
/*** @param {character[][]} board* @param {string} word* @return {boolean}*/
var exist = function (board, word) {const m = board.length;const n = board[0].length;const dirs = [-1, 0, 1, 0, -1];const dfs = (i, j, k) => {if (k == word.length) {return true;}if (i < 0 || i >= m || j < 0 || j >= n || board[i][j] != word[k]) {return false;}board[i][j] = ' ';let ans = false;for (let l = 0; l < 4; ++l) {ans = ans || dfs(i + dirs[l], j + dirs[l + 1], k + 1);}board[i][j] = word[k];return ans;};for (let i = 0; i < m; ++i) {for (let j = 0; j < n; ++j) {if (dfs(i, j, 0)) {return true;}}}return false;
};
C#
public class Solution {private char[][] board;private string word;private int m;private int n;public bool Exist(char[][] board, string word) {m = board.Length;n = board[0].Length;this.board = board;this.word = word;for (int i = 0; i < m; ++i) {for (int j = 0; j < n; ++j) {if (dfs(i, j, 0)) {return true;}}}return false;}private bool dfs(int i, int j, int k) {if (k == word.Length) {return true;}if (i < 0 || i >= m || j < 0 || j >= n || word[k] != board[i][j]) {return false;}board[i][j] = ' ';int[] dirs = {-1, 0, 1, 0, -1};bool ans = false;for (int l = 0; l < 4; ++l) {ans = ans || dfs(i + dirs[l], j + dirs[l + 1], k + 1);}board[i][j] = word[k];return ans;}
}
Swift
class Solution {private var board: [[Character]]private var word: Stringprivate var m: Intprivate var n: Intinit() {self.board = []self.word = ""self.m = 0self.n = 0}func exist(_ board: [[Character]], _ word: String) -> Bool {self.board = boardself.word = wordm = board.countn = board[0].countfor i in 0..<m {for j in 0..<n {if dfs(i, j, 0) {return true}}}return false}private func dfs(_ i: Int, _ j: Int, _ k: Int) -> Bool {if k == word.count {return true}if i < 0 || i >= m || j < 0 || j >= n || board[i][j] != word[word.index(word.startIndex, offsetBy: k)] {return false}let temp = board[i][j]board[i][j] = " "let dirs = [-1, 0, 1, 0, -1]var ans = falsefor l in 0..<4 {let ni = i + dirs[l]let nj = j + dirs[l + 1]if dfs(ni, nj, k + 1) {ans = truebreak}}board[i][j] = tempreturn ans}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/397537.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java的反射原理

反射允许程序在运行时检查或修改其类、接口、字段和方法的行为。反射主要通过java.lang.reflect包中的类和接口实现&#xff0c;它主要用于以下目的&#xff1a; 在运行时分析类的能力&#xff1a;通过反射&#xff0c;可以在运行时检查类的结构&#xff0c;比如它的方法、构造…

【RAG检索增强生成】Ollama+AnythingLLM本地搭建RAG大模型私有知识库

目录 前言一、Ollama&#xff1a;革新性的本地LLM服务工具1.核心优势2.技术亮点 二、AnythingLLM 概览1.核心特性2.技术生态支持 三、搭建本地智能知识库1. Ollama的安装启航2. AnythingLLM的安装对接3. AnythingLLM的配置精调4. 工作区与文档管理5. 聊天与检索的智能交互 四、…

计算机毕业设计 校园失物招领网站 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

封装el-table 基于element封装可配置JSON表格组件

基于element封装可配置JSON表格组件 话不多说直接贴代码&#xff0c;复制运行即可查看效果 子组件全部代码 <template><div class"custom-table"><el-table:data"tableData"borderstyle"width: 100%"size"mini"max-h…

负载均衡之HAProxy超全内容!!!

一、负载均衡 1.1 负载均衡概念 负载均衡&#xff08;Load Balance&#xff0c;简称 LB&#xff09;是高并发、高可用系统必不可少的关键组件&#xff0c;目标是尽力将网络流量平均分发到多个服务器上&#xff0c;以提高系统整体的响应速度和可用性。 1.2 软件负载均衡 软件…

做报表用什么工具?不想再用Excel了!!!

一、什么是中国式报表&#xff1f; 不知道大家现在还是使用Excel来制作报表&#xff0c;然后跟领导汇报工作吗&#xff1f;虽然Excel功能很强大&#xff0c;但是用Excel做过中国式报表的小伙伴一定知道它的制作过程有多复杂。 中国式报表可以用一句话简单概括&#xff1a;格式…

Mozilla Firefox侧边栏和垂直标签在131 Nightly版本中开始试用

垂直选项卡和全新的侧边栏体验现已在Mozilla Firefox Nightly 131 中提供。这一更新备受社区期待和要求&#xff0c;我们期待看到它如何提高您的浏览效率和工作效率。如果您想体验一下这项正在进行中的工作&#xff0c;请这样操作&#xff1a; 更新到最新的Nightly版 转到设置…

uniapp本地打包app安装说明

uniapp本地打包app安装说明 目录 uniapp本地打包app安装说明一、打包说明1.HBuilder X 生成本地打包资源2.Android Studio和App离线SDK环境准备2.1 下载Android Studio和 App离线SDK2.2 资源替换2.3 id属性值修改。2.4 添加provider信息到AndroidManifest.xml中的<applicati…

使用Hugging Face构建大型语言模型应用

在本文中&#xff0c;我们将介绍如何使用Hugging Face的大型语言模型&#xff08;LLM&#xff09;构建一些常见的应用&#xff0c;包括摘要&#xff08;Summarization&#xff09;、情感分析&#xff08;Sentiment analysis&#xff09;、翻译&#xff08;Translation&#xff…

Leetcode JAVA刷刷站(14)最长公共前缀

一、题目概述 二、思路方向 在Java中&#xff0c;要编写一个函数来查找字符串数组中的最长公共前缀&#xff0c;我们可以遵循以下步骤&#xff1a; 处理边界条件&#xff1a;如果数组为空或长度为0&#xff0c;直接返回空字符串。初始化最长公共前缀&#xff1a;将数组的第一个…

HarmonyOS 3.1/4.0应用升级到HarmonyOS NEXT改动点

在 “2024鸿蒙零基础快速实战-仿抖音App开发&#xff08;ArkTS版&#xff09;”&#xff08;https://coding.imooc.com/class/843.html&#xff09;视频课程中&#xff0c;因为讲师在该课程授课时是使用的HarmonyOS 3.1/4.0应用&#xff08;API 9&#xff09;&#xff0c;如果部…

在亚马逊云科技上搭建云原生生成式AI教育学习平台

项目简介&#xff1a; 小李哥将继续每天介绍一个基于亚马逊云科技AWS云计算平台的全球前沿AI技术解决方案&#xff0c;帮助大家快速了解国际上最热门的云计算平台亚马逊云科技AWS AI最佳实践&#xff0c;并应用到自己的日常工作里。 本次介绍的是如何利用亚马逊云科技大模型托…

1.2 C 语言环境:MinGW 与 CLion 的安装与配置

目录 1 C 语言的由来 2 安装 MinGW 编译器 3 Windows 中安装 CLion 开发环境 3.1 安装 CLion 开发环境 3.2 运行试用 30 天 3.3 新建项目​ 3.4 汉化 4 Mac 中安装 Clion 开发环境 4.1 安装 CLion 开发环境 4.2 运行试用 30 天 4.3 新建项目 ​4.4 汉化 5 向日葵的…

突破百度网盘的下载限速,两种方法教会你【超详细】

一、前言 Hello&#xff0c;大家后&#xff0c;我是博主英杰&#xff0c;前几天&#xff0c;我在使用百度网盘过程中&#xff0c;下载速度极慢&#xff0c;自己作为一个白嫖党&#xff0c;开会员也是心疼那点钱&#xff0c;所以在网上找了几个有效解决百度网盘限速问题的教程&a…

arcgis-坡度坡向分析

坡向的描述有定性和定量两种方式&#xff0c;定量是以东为0&#xff0c;顺时针递增&#xff0c;南为90&#xff0c;西为180&#xff0c;北为270等&#xff0c;范围在0&#xff5e;35959′59″之间。 定性描述有8方向法和4方向法. 8 方向为东、东南、南、西南、西、西北、北、东…

JavaWeb-01(Java进阶内容详解,Html、CSS、JS)

一、前端技术结构分析 网页的结构&#xff08;HTML&#xff09;、表现(CSS)、行为(JS) 1.HTML定义界面整体结构 2.CSS定义页面样式 3.JS实现动态效果 二、HTML 2.1安装VS Code及前端开发插件 Chinese (Simplified) (简体中文) Language Pack for Visual Studio Code Code Spe…

golang并发控制

常见的并发控制 常见的并发控制 channel:通过无缓冲的channel进行同步调用&#xff0c;有缓冲的channel进行异步调用&#xff0c;也可限制并发数量 waitgroup:可以通过add来动态调整&#xff0c;释放的时间需要使用defer 进行wg.done操作 context&#xff1a;通过在协程之间…

笔记本CPU天梯图(2024年8月),含AMD/骁龙等新CPU

原文地址&#xff08;高清无水印原图/持续更新/含榜单出处链接&#xff09;&#xff1a; 2024年8月笔记本CPU天梯图 2024年8月笔记本CPU天梯图 2024年8月5日更新日志&#xff1a;常规更新Cinebench R23、PassMark笔记本CPU天梯图&#xff0c;新增Geekbench 6.2单核多核天梯图&…

inner join, left join, right join, full join 的区别

1. 初始化表结构 SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS 0;-- ---------------------------- -- Table structure for t_city -- ---------------------------- DROP TABLE IF EXISTS t_city; CREATE TABLE t_city (id varchar(255) CHARACTER SET utf8mb4 COLLATE utf…

Windows Server修改远程桌面端口

新建入站规则 填写端口 允许连接 修改远程桌面端口 winR打开注册表 计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\Wds\rdpwd\Tds\tcp修改PortNumber为新端口 计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\Wi…