剑指offer--回溯
JZ12 矩阵中的路径
题目地址
描述
请设计一个函数,用来判断在一个n乘m的矩阵中是否存在一条包含某长度为len的字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。 例如
[
a
b
c
e
s
f
c
s
a
d
e
e
]
\begin{bmatrix} a & b &c & e\\ s & f &c&s\\ a&d&e&e\end{bmatrix} \quad
⎣⎡asabfdcceese⎦⎤
矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。
数据范围:,
0 ≤ n , m ≤ 20,1 ≤ len ≤ 25
进阶:时间复杂度0(n^2), 空间复杂度0(n^2)
示例1
输入:
[[a,b,c,e],[s,f,c,s],[a,d,e,e]],"abcced"
返回值:
true
示例2
输入:
[[a,b,c,e],[s,f,c,s],[a,d,e,e]],"abcb"
返回值:
false
备注:
0 <= matrix.length <= 200
0 <= matrix[i].length <= 200
代码
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param matrix char字符型二维数组
* @param word string字符串
* @return bool布尔型
*/
public boolean hasPath (char[][] matrix, String word) {
// write code here
if(matrix==null||matrix[0]==null||word==null) return false;
char[] strs=word.toCharArray();
for(int i=0;i<matrix.length;i++){
for(int j=0;j<matrix[0].length;j++){
if(matrix[i][j]==strs[0]){
boolean[][]visit=new boolean[matrix.length][matrix[0].length];
visit[i][j]=true;
if(dfs(matrix,strs,1,i,j,visit)){
return true;
}
}
}
}
return false;
}
/*
*matrix:字符数组
*word:要匹配的单词串
*index:遍历到第index个单词
*(i,j)matrix数组下标
*visit[][]:判断某个单词是否被问过
*/
public boolean dfs(char[][] matrix,char[] word,int index,int i,int j,boolean[][] visit){
//待匹配字符串遍历完
if(index>=word.length){
return true;
}
//四个方向可以进行遍历
int[][] f={{1,-1,0,0},{0,0,1,-1}};
boolean find=false;//判断是否找到匹配串
for(int k=0;k<4;k++){
//越界
if(i+f[0][k]<0 || i+f[0][k]>=matrix.length || j+f[1][k]<0 || j+f[1][k]>=matrix[0].length){
continue;
}
//已经访问过
if(visit[i+f[0][k]][j+f[1][k]]) continue;
//只有要遍历的字符值 = word中的值时才遍历
if(matrix[i+f[0][k]][j+f[1][k]]==word[index]){
visit[i+f[0][k]][j+f[1][k]]=true;
find=find||dfs(matrix,word,index+1,i+f[0][k],j+f[1][k],visit);
visit[i+f[0][k]][j+f[1][k]]=false;
}
}
return find;
}
}
JZ13 机器人的运动范围
题目地址
描述
地上有一个 rows 行和 cols 列的方格。坐标从 [0,0] 到 [rows-1,cols-1] 。一个机器人从坐标 [0,0] 的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于 threshold 的格子。 例如,当 threshold 为 18 时,机器人能够进入方格 [35,37] ,因为 3+5+3+7 = 18。但是,它不能进入方格 [35,38] ,因为 3+5+3+8 = 19 。请问该机器人能够达到多少个格子?
数据范围: 0 ≤ threshold ≤ 15,1≤ cols,rows ≤ 100
进阶:空间复杂度0(nm) ,时间复杂度0(nm)
示例1
输入:
1,2,3
返回值:
3
示例2
输入:
0,1,3
返回值:
1
示例3
输入:
10,1,100
返回值:
29
说明:
[0,0],[0,1],[0,2],[0,3],[0,4],[0,5],[0,6],[0,7],[0,8],[0,9],[0,10],[0,11],[0,12],[0,13],[0,14],[0,15],[0,16],[0,17],[0,18],[0,19],[0,20],[0,21],[0,22],[0,23],[0,24],[0,25],[0,26],[0,27],[0,28] 这29种,后面的[0,29],[0,30]以及[0,31]等等是无法到达的
示例4
输入:
5,10,10
返回值:
21
代码
public class Solution {
public int movingCount(int threshold, int rows, int cols) {
boolean[][]visit=new boolean[rows][cols];
int count= dfs(threshold,0,0,rows,cols,visit);
for(int i=0;i<visit.length;i++){
for(int j=0;j<visit[0].length;j++){
System.out.print(i+","+j+"("+visit[i][j]+") ");
}
System.out.println();
}
return count;
}
/*
*(i,j)是坐标,表示到达了那个位置
*rows,cols表示位置矩阵的行和列
*visit[][]判断某个位置是否被访问过
*/
public int dfs(int threshold,int i,int j,int rows,int cols,boolean[][] visit){
visit[i][j]=true;
int count=1;
int[][] f={{1,-1,0,0},{0,0,1,-1}};
for(int k=0;k<4;k++){
if(i+f[0][k]<0 || i+f[0][k]>=rows || j+f[1][k]<0 || j+f[1][k]>=cols){
continue;
}
if(visit[i+f[0][k]][j+f[1][k]]) continue;
if(!isValid(i+f[0][k],j+f[1][k],threshold)) continue;
visit[i+f[0][k]][j+f[1][k]]=true;
count+=dfs(threshold,i+f[0][k],j+f[1][k],rows,cols,visit);
}
return count;
}
//判断坐标(i,j)是否是有效的,即坐标i,j数位和小于等于threshold
public boolean isValid(int i,int j,int threshold){
int count=0;
while(i>0){
count+=i%10;
i/=10;
}
while(j>0){
count+=j%10;
j/=10;
}
return count<=threshold;
}
}