/** 主要思路: 1:难点:如果一个节点被走过,需要标记。但是!当这个节点走不通时,就需要退回来再找另外的路。。这时候问题就来了。当换另外一条路时,其他节点有可能走到刚标记的路上来。这时候原来的标记就需要清楚。 a b c d b c e f d r m n 字符串abcbc 开始a(0,0)- b(0,1)-c(1,1)-b(1,0) 然后走不动了 需要退回到 c(1,1) 但是 也不能走动,因为b已经标记了。 所以一直退回到 a(0,0) 然后只有 b(1, 0)要走了,但是此时需要清楚其标记。所以解决方法: 每次标记的限制都是限制前一位的选择,所以保存这个变量。退回时,如果选择了其他位置,该位置标志被清除。或者再退回上一级时,也清除。 **/ import java.util.Stack; public class Solution { public boolean hasPath(char[] mat, int rows, int cols, char[] str){ if(mat == null || rows < 1 || cols < 1 || rows * cols != mat.length || mat.length < str.length){ return false; } Stack<Integer> stack = new Stack<>(); boolean[] isVis = new boolean[mat.length];//位置访问信息 int i = 0; int j = 0; int m = -1; while(i < mat.length && j < str.length){ if(j == 0){ //找第一个位置 if(!isVis[i] && mat[i] == str[j]){//如果没有访问过且与str对应的相等就入栈 stack.push(i); // 入栈 if(m > -1){//如果m记录的前一节点的值 isVis[m] = false;//清除记忆 } isVis[i] = true; j++; }else{//否者,继续遍历matrix i++; } }else{ int k = stack.peek(); //查看栈顶元素 if(k - cols >= 0 && !isVis[k - cols] && mat[k - cols] == str[j]){//上一行是否匹配 stack.push(k - cols); if(m > -1){//如果m记录的前一节点的值 isVis[m] = false;//清除记忆 } isVis[k - cols] = true; j++; continue; } if(k % cols != 0 && !isVis[k - 1] && mat[k - 1] == str[j]){//上一位是否匹配 stack.push(k - 1); if(m > -1){//如果m记录的前一节点的值 isVis[m] = false;//清除记忆 } isVis[k - 1] = true; j++; continue; } if(k % cols != cols - 1 && !isVis[k + 1] && mat[k + 1] == str[j]){//下一位 stack.push(k + 1); if(m > -1){//如果m记录的前一节点的值 isVis[m] = false;//清除记忆 } isVis[k + 1] = true; j++; continue; } if(k + cols < mat.length && !isVis[k + cols] && mat[k + cols] == str[j]){//下一行 stack.push(k + cols); if(m > -1){//如果m记录的前一节点的值 isVis[m] = false;//清除记忆 } isVis[k + cols] = true; j++; continue; } m = stack.pop(); //如果没有找到通路。这个节点就废弃,记录下该点位置。。 j--; //str的指针也前移重新判断 } } return j == str.length; //str遍历完成就表示true了 } }