剑指Offer编程链接:JZ12
题目描述:
思路:递归+回溯的方法,总结一下什么情况需要使用递归:
递归在解决问题时,通常涉及以下情况:
- 问题可被分解为较小的相似子问题。
- 子问题与原问题具有相同的结构,只是规模更小。
- 每个子问题的解可以通过递归调用来获得。
- 存在基本情况,当问题足够小时可以直接求解。
递归适用于许多问题,如数学运算(如阶乘、斐波那契数列)、树结构遍历、图算法、字符串处理等。然而,使用递归时要注意合适的终止条件和避免出现无限递归。
具体做法:
step 1:优先处理矩阵为空的特殊情况。
step 2:设置flag数组记录某一次路径中矩阵中的位置是否被经过,因此一条路径不能回头。
step 3:遍历矩阵,对每个位置进行递归。
step 4:递归查找的时候,到了矩阵的边界或者是下一个字符与这个位置的字符不匹配,或者节点已经访问过了,或者字符串匹配完成都结束递归。
step 5:访问节点,修改flag数组,向其他四个方向延伸,回溯的时候修改flag数组。
代码:
java
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param matrix char字符型二维数组
* @param word string字符串
* @return bool布尔型
*/
//i代表数组行,j代表列,matrix代表矩阵,n*m 矩阵,word代表要匹配的字符串,k代表当前第几个字符
private boolean dfs(char[][] matrix,int n,int m,int i,int j,String word,int k,boolean[][] flag){
//下标越界、字符不匹配、已经遍历过不能重复
if(i<0||i>=n||j<0||j>=m||(matrix[i][j]!=word.charAt(k))||(flag[i][j]==true)){
return false;
}
if(k==word.length()-1){
return true;
}
flag[i][j] = true;
//该结点四个方向
if(dfs(matrix,n,m,i-1,j,word,k+1,flag)||dfs(matrix,n,m,i+1,j,word,k+1,flag)||dfs(matrix,n,m,i,j-1,word,k+1,flag)||dfs(matrix,n,m,i,j+1,word,k+1,flag)){
return true;
}
//此格未被占用
flag[i][j] = false;
return false;
}
public boolean hasPath (char[][] matrix, String word) {
// write code here
if(matrix.length == 0){
return false;
}
int n = matrix.length;
int m = matrix[0].length;
boolean[][] flag = new boolean[n][m];
for(int i = 0;i<n;i++){
for(int j = 0;j<m;j++){
if(dfs(matrix,n,m,i,j,word,0,flag)){
return true;
}
}
}
return false;
}
}