【Java】 剑指offer(11) 矩阵中的路径
本文参考自《剑指offer》一书,代码采用Java语言。
题目
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中任意一格开始,每一步可以在矩阵中向左、右、上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。例如在下面的3×4的矩阵中包含一条字符串“bfce”的路径(路径中的字母用下划线标出)。但矩阵中不包含字符串“abfb”的路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入这个格子。
A B T G
C F C S
J D E H
思路
首先对所整个矩阵遍历,找到第一个字符,然后向上下左右查找下一个字符,由于每个字符都是相同的判断方法(先判断当前字符是否相等,再向四周查找),因此采用递归函数。由于字符查找过后不能重复进入,所以还要定义一个与字符矩阵大小相同的布尔值矩阵,进入过的格子标记为true。如果不满足的情况下,需要进行回溯,此时,要将当前位置的布尔值标记回false。(所谓的回溯无非就是对使用过的字符进行标记和处理后的去标记)
测试用例
1.功能测试(多行多列矩阵中存在或者不存在路径)
2.边界值测试(矩阵只有一行;矩阵与路径的所有字符都相同)
3.特殊输入测试(null)
完整Java代码
(含测试代码)
/**
*
* @Description 面试题12:矩阵中的路径
*
* @author yongh
* @date 2018年9月16日 上午11:13:48
*/ // 题目:请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有
// 字符的路径。路径可以从矩阵中任意一格开始,每一步可以在矩阵中向左、右、
// 上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入
// 该格子。例如在下面的3×4的矩阵中包含一条字符串“bfce”的路径(路径中的字
// 母用下划线标出)。但矩阵中不包含字符串“abfb”的路径,因为字符串的第一个
// 字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入这个格子。
// A B T G
// C F C S
// J D E H public class StringPathInMatrix {
public boolean hasPath(char[] matrix, int rows, int cols, char[] str) {
if (matrix == null || rows < 1 || cols < 1 || str == null) {
return false;
}
boolean[] isVisited = new boolean[rows * cols];
for (boolean v : isVisited) {
v = false;
}
int pathLength = 0;
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) {
if (hasPathCore(matrix, rows, cols, row, col, str, pathLength, isVisited))
return true;
}
}
return false;
} private boolean hasPathCore(char[] matrix, int rows, int cols, int row, int col, char[] str, int pathLength,
boolean[] isVisited) {
if (row < 0 || col < 0 || row >= rows || col >= cols || isVisited[row * cols + col] == true
|| str[pathLength] != matrix[row * cols + col])
return false;
if (pathLength == str.length - 1)
return true;
boolean hasPath = false;
isVisited[row * cols + col] = true;
hasPath = hasPathCore(matrix, rows, cols, row - 1, col, str, pathLength + 1, isVisited)
|| hasPathCore(matrix, rows, cols, row + 1, col, str, pathLength + 1, isVisited)
|| hasPathCore(matrix, rows, cols, row, col - 1, str, pathLength + 1, isVisited)
|| hasPathCore(matrix, rows, cols, row, col + 1, str, pathLength + 1, isVisited); if (!hasPath) {
isVisited[row * cols + col] = false;
}
return hasPath;
} // =======测试代码======== // A B T G
// C F C S
// J D E H // BFCTB
public void test1() {
char[] matrix = "ABTGCFCSJDEH".toCharArray();
int rows = 3;
int cols = 4;
char[] str = "BFCTB".toCharArray();
if (!hasPath(matrix, rows, cols, str))
System.out.println("Test1 passed.");
else
System.out.println("Test1 failed.");
} // A B T G
// C F C S
// J D E H // BFCE
public void test2() {
char[] matrix = "ABTGCFCSJDEH".toCharArray();
int rows = 3;
int cols = 4;
char[] str = "BFCE".toCharArray();
if (hasPath(matrix, rows, cols, str))
System.out.println("Test2 passed.");
else
System.out.println("Test2 failed.");
} // matrix=null
public void test3() {
char[] matrix = null;
int rows = 0;
int cols = 0;
char[] str = "BFCE".toCharArray();
if (!hasPath(matrix, rows, cols, str))
System.out.println("Test3 passed.");
else
System.out.println("Test3 failed.");
} // str=null
public void test4() {
char[] matrix = "ABTGCFCSJDEH".toCharArray();
int rows = 3;
int cols = 4;
char[] str = null;
if (!hasPath(matrix, rows, cols, str))
System.out.println("Test4 passed.");
else
System.out.println("Test4 failed.");
} // A // A
public void test5() {
char[] matrix = "A".toCharArray();
int rows = 1;
int cols = 1;
char[] str = "A".toCharArray();
if (hasPath(matrix, rows, cols, str))
System.out.println("Test5 passed.");
else
System.out.println("Test5 failed.");
} // A // B
public void test6() {
char[] matrix = "A".toCharArray();
int rows = 1;
int cols = 1;
char[] str = "B".toCharArray();
if (!hasPath(matrix, rows, cols, str))
System.out.println("Test6 passed.");
else
System.out.println("Test6 failed.");
} // AAAA
// AAAA
// AAAA // AAAAAAAAAAAA
public void test7() {
char[] matrix = "AAAAAAAAAAAA".toCharArray();
int rows = 3;
int cols = 4;
char[] str = "AAAAAAAAAAAA".toCharArray();
if (hasPath(matrix, rows, cols, str))
System.out.println("Test7 passed.");
else
System.out.println("Test7 failed.");
} public static void main(String[] args) {
StringPathInMatrix demo = new StringPathInMatrix();
demo.test1();
demo.test2();
demo.test3();
demo.test4();
demo.test5();
demo.test6();
demo.test7();
}
}
Test1 passed.
Test2 passed.
Test3 passed.
Test4 passed.
Test5 passed.
Test6 passed.
Test7 passed.
StringPathInMatrix
收获
1.回溯法用于多个步骤,每个步骤有多个选项的问题:若当前步骤满足条件,给定一个标记,当发现之后的步骤不满足条件时,去除标记。
2.字符串转为字符数组,使用toCharArray()方法
3.二维数组下标的计算:row*cols+col,小心别搞错。
【Java】 剑指offer(11) 矩阵中的路径的更多相关文章
- 剑指 Offer 12. 矩阵中的路径 + 递归 + 深搜 + 字符串问题
剑指 Offer 12. 矩阵中的路径 题目链接 题目类似于迷宫的搜索. 需要注意的是,需要首先判断起始搜索的位置,可能有多个起点,都需要一一尝试. 每轮迭代的时候记得将是否遍历标记数组还原为未遍历的 ...
- 力扣 - 剑指 Offer 12. 矩阵中的路径
题目 剑指 Offer 12. 矩阵中的路径 思路1(回溯.DFS) 这题可以使用回溯+递归来解决,思路如下: 将二维数组的每一个元素都作为起点进行回溯查找 每次查找的时候,都有四个方向,但是上一个方 ...
- Go语言实现:【剑指offer】矩阵中的路径
该题目来源于牛客网<剑指offer>专题. 请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径.路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向 ...
- 剑指offer:矩阵中的路径(递归回溯法DFS类似迷宫)
1. 题目描述 /* 请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径. 路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子. 如果一条 ...
- 剑指Offer 65. 矩阵中的路径 (回溯)
题目描述 请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径.路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子.如果一条路径经过了矩阵中 ...
- [剑指Offer] 65.矩阵中的路径
题目描述 请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径.路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子.如果一条路径经过了矩阵中 ...
- 剑指offer——13矩阵中的路径
题目描述 请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径.路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子.如果一条路径经过了矩阵中 ...
- 剑指 Offer 12. 矩阵中的路径
题目描述 是一道很常见的深搜题目,不过里面要考虑一些边界问题,比如走过的路径是不能再次走入的,所以我这里我自己的 代码想到是利用一个新的二维的数组,记录走过的路径,不过题解的直接将原二维数组中的路径隐 ...
- [剑指Offer]12-矩阵中的路径(回溯)
题目链接 https://www.nowcoder.com/practice/c61c6999eecb4b8f88a98f66b273a3cc?tpId=13&tqId=11218&t ...
随机推荐
- edusoho -A5: ApiBundle UML
edusoho -A5: ApiBundle UML
- 使pre的内容自动换行(转)
<pre> 元素可定义预格式化的文本.被包围在 pre 元素中的文本通常会保留空格和换行符.而文本也会呈现为等宽字体. <pre> 标签的一个常见应用就是用来表示计算机的源代码 ...
- 整体二分(SP3946 K-th Number ZOJ 2112 Dynamic Rankings)
SP3946 K-th Number (/2和>>1不一样!!) #include <algorithm> #include <bitset> #include & ...
- 在 Angular6 中使用 HTTP 请求服务端数据
第一步 准备好api接口地址, 例如 https://api.example.com/api/ 第二步 在根组件 app.module.ts 中引入 HttpClientModule 模块. // a ...
- Day044--javascript, ECMAScript
一. javascript JavaScript基础分为三个部分: ECMAScript:JavaScript的语法标准.包括变量.表达式.运算符.函数.if语句.for语句等. DOM:操作网页上的 ...
- pytest 12 函数传参和fixture传参数request
前沿: 有的case,需要依赖于某些特定的case才可以执行,比如,登陆获取到的cookie,每次都需要带着他,为了确保是同一个用户,必须带着和登陆获取到的同一个cookies. 大部分的用例都会先登 ...
- DOS批处理:FOR中的Delims和Tokens参数
在For命令语句的参数F中,最难理解的就是Delims和Tokens两个选项,本文简单的做一个比较和总结. “For /f”常用来解析文本,读取字符串.分工上,delims负责切分字符串,而token ...
- linux 触摸屏驱动
目录 linux 触摸屏驱动 输入子系统怎么写? 触摸屏事件 事件分类 事件设置 硬件配置 设计思路 完整程序 测试 ts_lib 使用 问题小结 title: linux 触摸屏驱动 tags: l ...
- DirectX11 With Windows SDK--17 利用几何着色器实现公告板效果
前言 上一章我们知道了如何使用几何着色器将顶点通过流输出阶段输出到绑定的顶点缓冲区.接下来我们继续利用它来实现一些新的效果,在这一章,你将了解: 实现公告板效果 Alpha-To-Coverage 对 ...
- 第六节:WebApi的部署方式(自托管)
一. 简单说明 开篇就介绍过WebApi和MVC相比,其中优势之一就是WebApi可以不依赖于IIS部署,可以自托管,当然这里指的是 .Net FrameWork 下的 WebApi 和 MVC 相比 ...