/**
主要思路:
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了
}
}