【剑指Offer学习】【面试题66:矩阵中的路径】
题目:请设计一个函数,用来推断在一个矩阵中是否存在一条包括某字符串全部字符的路径。路径能够从矩阵中随意一格開始。每一步能够在矩阵中间向左、右、上、下移动一格。假设一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。
举例分析
比如在以下的3*4的矩阵中包括一条字符串”bcced”的路径。
但矩阵中不包括字符串“abcb”的路径,因为字符串的第一个字符b占领了矩阵中的第一行第二格子之后,路径不能再次进入这个格子。
a b c e
s f c s
a d e e
解题思路
这是一个能够用回朔法解决的典型题。首先,在矩阵中任选一个格子作为路径的起点。假设矩阵中某个格子的字符为ch,那么这个格子不可能处在路径上的第i个位置。假设路径上的第i个字符不是ch。那么这个格子不可能处在路径上的第i个位置。假设路径上的第i个字符正好是ch。那么往相邻的格子寻找路径上的第i+1个字符。除在矩阵边界上的格子之外,其它格子都有4个相邻的格子。反复这个过程知道路径上的全部字符都在矩阵中找到相应的位置。
因为回朔法的递归特性,路径能够被开成一个栈。当在矩阵中定位了路径中前n个字符的位置之后。在与第n个字符相应的格子的周围都没有找到第n+1个字符。这个时候仅仅要在路径上回到第n-1个字符。又一次定位第n个字符。
因为路径不能反复进入矩阵的格子。还须要定义和字符矩阵大小一样的布尔值矩阵,用来标识路径是否已经进入每个格子。
当矩阵中坐标为(row,col)的格子和路径字符串中下标为pathLength的字符一样时。从4个相邻的格子(row,col-1),(row-1,col),(row,col+1)以及(row+1,col)中去定位路径字符串中下标为pathLength+1的字符。
假设4个相邻的格子都没有匹配字符串中下标为pathLength+1的字符,表明当前路径字符串中下标为pathLength的字符在矩阵中的定位不对,我们须要回到前一个字符(pathLength-1),然后又一次定位。
一直反复这个过程,直到路径字符串上全部字符都在矩阵中找到合适的位置
代码实现
public class Test66 {
/**
* 题目:请设计一个函数。用来推断在一个矩阵中是否存在一条包括某字符串全部字符的路径。
* 路径能够从矩阵中随意一格開始。每一步能够在矩阵中间向左、右、上、下移动一格。
* 假设一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。
*
* @param matrix 输入矩阵
* @param rows 矩阵行数
* @param cols 矩阵列数
* @param str 要搜索的字符串
* @return 是否找到 true是。false否
*/
public static boolean hasPath(char[] matrix, int rows, int cols, char[] str) {
// 參数校验
if (matrix == null || matrix.length != rows * cols || str == null || str.length < 1) {
return false;
}
// 变量初始化
boolean[] visited = new boolean[rows * cols];
for (int i = 0; i < visited.length; i++) {
visited[i] = false;
}
// 记录结果的数组。
int[] pathLength = {0};
// 以每个点为起始进行搜索
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (hasPathCore(matrix, rows, cols, str, visited, i, j, pathLength)) {
return true;
}
}
}
return false;
}
/**
* 回溯搜索算法
*
* @param matrix 输入矩阵
* @param rows 矩阵行数
* @param cols 矩阵列数
* @param str 要搜索的字符串
* @param visited 訪问标记数组
* @param row 当前处理的行号
* @param col 当前处理的列号
* @param pathLength 已经处理的str中字符个数
* @return 是否找到 true是,false否
*/
private static boolean hasPathCore(char[] matrix, int rows, int cols, char[] str, boolean[] visited,
int row, int col, int[] pathLength) {
if (pathLength[0] == str.length) {
return true;
}
boolean hasPath = false;
// 推断位置是否合法
if (row >= 0 && row < rows
&& col >= 0 && col < cols
&& matrix[row * cols + col] == str[pathLength[0]]
&& !visited[row * cols + col]) {
visited[row * cols + col] = true;
pathLength[0]++;
// 按左上右下进行回溯
hasPath = hasPathCore(matrix, rows, cols, str, visited, row, col - 1, pathLength)
|| hasPathCore(matrix, rows, cols, str, visited, row - 1, col, pathLength)
|| hasPathCore(matrix, rows, cols, str, visited, row, col + 1, pathLength)
|| hasPathCore(matrix, rows, cols, str, visited, row + 1, col, pathLength);
if (!hasPath) {
pathLength[0]--;
visited[row * cols + col] = false;
}
}
return hasPath;
}
public static void main(String[] args) {
//ABCE //ABCCED
//SFCS
//ADEE
System.out.println(hasPath("ABCESFCSADEE".toCharArray(), 3, 4,
"ABCCED".toCharArray()) + "[true]");// true
//ABCE //SEE
//SFCS
//ADEE
System.out.println(hasPath("ABCESFCSADEE".toCharArray(), 3, 4,
"SEE".toCharArray()) + "[true]");// true
//ABCE //ABCB
//SFCS
//ADEE
System.out.println(hasPath("ABCESFCSADEE".toCharArray(), 3, 4,
"ABCB".toCharArray()) + "[false]");// false
//ABCEHJIG //SLHECCEIDEJFGGFIE
//SFCSLOPQ
//ADEEMNOE
//ADIDEJFM
//VCEIFGGS
System.out.println(hasPath("ABCEHJIGSFCSLOPQADEEMNOEADIDEJFMVCEIFGGS".toCharArray(), 5, 8,
"SLHECCEIDEJFGGFIE".toCharArray()) + "[true]");// true
//ABCEHJIG //SGGFIECVAASABCEHJIGQEM
//SFCSLOPQ //
//ADEEMNOE
//ADIDEJFM
//VCEIFGGS
System.out.println(hasPath("ABCEHJIGSFCSLOPQADEEMNOEADIDEJFMVCEIFGGS".toCharArray(), 5, 8,
"SGGFIECVAASABCEHJIGQEM".toCharArray()) + "[true]");// true
//ABCEHJIG //SGGFIECVAASABCEEJIGOEM
//SFCSLOPQ
//ADEEMNOE
//ADIDEJFM
//VCEIFGGS
System.out.println(hasPath("ABCEHJIGSFCSLOPQADEEMNOEADIDEJFMVCEIFGGS".toCharArray(), 5, 8,
"SGGFIECVAASABCEEJIGOEM".toCharArray()) + "[false]");// false
//ABCEHJIG //SGGFIECVAASABCEHJIGQEMS
//SFCSLOPQ
//ADEEMNOE
//ADIDEJFM
//VCEIFGGS
System.out.println(hasPath("ABCEHJIGSFCSLOPQADEEMNOEADIDEJFMVCEIFGGS".toCharArray(), 5, 8,
"SGGFIECVAASABCEHJIGQEMS".toCharArray()) + "[false]");// false
//AAAA //AAAAAAAAAAAA
//AAAA
//AAAA
System.out.println(hasPath("AAAAAAAAAAAA".toCharArray(), 3, 4,
"AAAAAAAAAAAA".toCharArray()) + "[true]");// true
//AAAA //AAAAAAAAAAAAA
//AAAA
//AAAA
System.out.println(hasPath("AAAAAAAAAAAA".toCharArray(), 3, 4,
"AAAAAAAAAAAAA".toCharArray()) + "[false]");// false
}
}
执行结果
特别说明
欢迎转载,转载请注明出处【http://blog.csdn.net/DERRANTCM/article/details/46887767】
【剑指Offer学习】【面试题66:矩阵中的路径】的更多相关文章
- 【剑指Offer】面试题12. 矩阵中的路径
题目 请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径.路径可以从矩阵中的任意一格开始,每一步可以在矩阵中向左.右.上.下移动一格.如果一条路径经过了矩阵的某一格,那么该路径 ...
- 《剑指offer》面试题12. 矩阵中的路径
问题描述 请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径.路径可以从矩阵中的任意一格开始,每一步可以在矩阵中向左.右.上.下移动一格.如果一条路径经过了矩阵的某一格,那么该 ...
- 剑指Offer(书):矩阵中的路径
题目: * 请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径.* 路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子.* 如果一条路径经 ...
- 剑指offer笔记面试题12----矩阵中的路径
题目:请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径.路径可以从矩阵中的任意一格开始,每一步可以在矩阵中向左.右.上.下移动一格.如果一条路径经过了矩阵的某一格,那么该路径 ...
- 【剑指offer】面试题 15. 二进制中 1 的个数
面试题 15. 二进制中 1 的个数 题目描述 题目:输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. Java 实现 方法一 public class Solution { // y ...
- 【剑指offer】面试题 22. 链表中倒数第 K 个节点
面试题 22. 链表中倒数第 K 个节点
- 《剑指offer》面试题66. 构建乘积数组
问题描述 给定一个数组 A[0,1,-,n-1],请构建一个数组 B[0,1,-,n-1],其中 B 中的元素 B[i]=A[0]×A[1]×-×A[i-1]×A[i+1]×-×A[n-1].不能使用 ...
- 《剑指offer》面试题45 圆圈中最后剩下的数字(Java版本)
引言 这道题网上的讲解都是直接抄书,没意思,所以想自己写一写,补充一下,便于自己理解.另外,大家都忽略了经典解法,虽然这种解法效率不及第二种,但是我觉得在项目当中阅读性其实很重要,牺牲一点点效率保证代 ...
- 剑指offer笔记面试题3----数组中重复的数字
题目一:找出数组中重复的数字.在一个长度为n的数组里的所有数字都在0~n-1的范围内.数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次.请找出数组中任意一个重复的数字.例如 ...
- 《剑指offer》面试题15 链表中的倒数第k个节点 Java版
书中方法:用两个节点一次遍历求得倒数第k个节点.注意头节点为空,k<=0,k大于节点个数的情况. public ListNode find(ListNode head, int k){ if(h ...
随机推荐
- Android开源git40个App源代码
(JamsMusicPlayer)非常棒的音乐播放器(new) (F8)日程安排的软件 (Conversations)基于XMPP的应用 (Bitocle)能够在手机上查看自己github ...
- 不为客户连接创建子进程的并发回射服务器( select实现 )
前言 在此前,我已经介绍了一种并发回射服务器实现( 点此进入 ).它通过调用fork函数为每个客户请求创建一个子进程.同时,我还为此服务器添加了自动消除僵尸子进程的机制.现在请想想,在客户量非常大的情 ...
- RDLC报表 报表数据 栏 快捷键
血淋淋的教训啊,这段时间用RDLC报表,创建报表后会在右边加载[服务器资源管理器][工具栏][报表数据]一些栏目 如图 [服务器资源管理器][工具栏]还好[报表数据]栏在开发的时候不小心点了X给关掉了 ...
- apktool + eclipse 动态调试APK
用了会AndBug,尽管挺强大的可是作为习惯了OD.EDB作为动态调试工具的人,自然有些不习惯,于是乎寻求新的动态调试解决方式.但大多数都是NetBeans + apktool.想着还得多下一个IDE ...
- EasyRTMP内置进入摄像机中实现网络推流直播摄像机的功能
本文转自博客:http://blog.csdn.net/jinlong0603/article/details/57468084 在前面的<如何用传统摄像机实现直接对接平台,类似于海康萤石.大华 ...
- Go Concurrency Patterns: Timing out, moving on
https://blog.golang.org/go-concurrency-patterns-timing-out-and
- 相机标定过程(opencv) + matlab参数导入opencv + matlab标定和矫正
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 辛苦原创所得,转载请注明出处 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ...
- javascript 正则表达式 详细入门教程
1.什么是正则表达式 定义: 一个用来搜索.匹配.处理一些符合特定语法规则的一个强大的字符串处理工具. 用途: 进行特定字符和字符串的搜索 替换字符串中指定的字符或字符串 验证字符串是否符合需求 2. ...
- Juery插件-- jquery.cookie.js
1.引入jquery <script src="scripts/jquery-1.8.8.js" type="text/javascript">&l ...
- Nginx中的惊群现象解决方法
*什么是惊群现象?Nginx中用了什么方法来避免这种问题的发生?本篇就解决这两个问题...→_→* 惊群现象的定义与危害 在Nginx中,每一个worker进程都是由master进程fork出来的.m ...