题目描述
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。例如4x3的矩阵 a b c e s f c s a d e e 矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。
import java.util.Arrays;
import java.util.Stack;
public class Solution {
boolean hasPath(char[] matrix, int rows, int cols, char[] str){
boolean[] ins = new boolean[matrix.length];
for(int i=0;i<matrix.length;i++){
Arrays.fill(ins, false);
if(matrix[i]==str[0]){
ins[i] = true;
Stack<Integer> stack = new Stack<Integer>();
stack.add(i);
int count = 1;
int index = 0;
while(count!=str.length && stack.size()!=0){
int j = stack.peek();
//上
index = (j/cols-1)*cols+j%cols;
if((j/cols-1)>=0 && !ins[index] && matrix[index]==str[count]){
stack.add(index);
ins[index] = true;
count++;
continue;
}
//下
index = (j/cols+1)*cols+j%cols;
if((j/cols+1)<rows && !ins[index]&& matrix[index]==str[count]){
stack.add(index);
ins[index] = true;
count++;
continue;
}
//左
index = (j/cols)*cols+j%cols-1;
if((j%cols-1)>=0 && !ins[index]&& matrix[index]==str[count]){
stack.add(index);
ins[index] = true;
count++;
continue;
}
//右
index = (j/cols)*cols+j%cols+1;
if((j%cols+1)<cols && !ins[index]&& matrix[index]==str[count]){
stack.add(index);
ins[index] = true;
count++;
continue;
}
stack.pop();
count--;
}
if(count==str.length) return true;
}
}
return false;
}
}
递归解法:
假设存在一个方法helper(int x,int y,char[] str)可以求出是否存在以(x,y)开始的,完成str的路径。
那么helper(int x,int y,char[] str)就等于自己是否符合str[0],并且四个方向上任意一个满足str[1...]
import java.util.Stack;
public class Solution {
public boolean hasPath(char[] matrix, int rows, int cols, char[] str){
if(str.length==0){
return true;
}
boolean[] flag = new boolean[matrix.length];
for(int i=0;i<cols;i++){
for(int j=0;j<rows;j++){
if(helper(flag,matrix,i,j,rows,cols,str,0)){
return true;
}
}
}
return false;
}
private boolean helper(boolean[] flag,char[] matrix, int x,int y,int rows, int cols, char[] str,int index){
if(str.length==index){
return true;
}
if(x<0 || y<0 || x>=cols || y>=rows){
return false;
}
if(flag[cols * y + x]){
return false;
}
if(matrix[cols * y + x]!=str[index]){
return false;
}
flag[cols * y + x] = true;
if(helper(flag,matrix,x-1,y,rows,cols,str,index+1)
|| helper(flag,matrix,x+1,y,rows,cols,str,index+1)
|| helper(flag,matrix,x,y-1,rows,cols,str,index+1)
|| helper(flag,matrix,x,y+1,rows,cols,str,index+1)){
return true;
}
flag[cols * y + x] = false;
return false;
}
}
非递归解法:
深入遍历,但是和简单的深度遍历不同,访问过的点可以再次访问(在下一次搜索中,同一次搜索不行)。
因此使用栈来进行深度遍历,对比递归方式,需要退栈后,需要知道下一次搜索是向哪个方向,避免重复向一个方向搜索进入死循环,因此需要有一个辅助栈来标记哪个方向已经搜索过了(使用1,2,3,4来代表四个方法)。
对于递归方法,因为方法栈已经替我们做了这个工作,因此不需要辅助栈。
import java.util.Arrays;
import java.util.Stack;
public class Solution {
boolean hasPath(char[] matrix, int rows, int cols, char[] str){
boolean[] flag = new boolean[matrix.length];
for(int i=0;i<cols;i++){
for(int j=0;j<rows;j++){
int index = 0;
if(matrix[j*cols+i]==str[index]){
Stack<Integer> stackX = new Stack<Integer>();
Stack<Integer> stackY = new Stack<Integer>();
Stack<Integer> stackNext = new Stack<Integer>();
stackX.push(i);
stackY.push(j);
stackNext.push(0);
while(!stackX.isEmpty() && stackX.size()<str.length){
int x = stackX.peek();
int y = stackY.peek();
flag[y*cols+x] = true;
int nextX = 0;
int nextY = 0;
if(stackNext.peek()<1 && isSafe(nextX=x-1,nextY=y,rows,cols,matrix,flag,str,stackX.size())){
stackNext.pop();
stackNext.push(1);
stackNext.push(0);
stackX.push(nextX);
stackY.push(nextY);
continue;
}
if(stackNext.peek()<2 && isSafe(nextX=x+1,nextY=y,rows,cols,matrix,flag,str,stackX.size())){
stackNext.pop();
stackNext.push(2);
stackNext.push(0);
stackX.push(nextX);
stackY.push(nextY);
continue;
}
if(stackNext.peek()<3 && isSafe(nextX=x,nextY=y-1,rows,cols,matrix,flag,str,stackX.size())){
stackNext.pop();
stackNext.push(3);
stackNext.push(0);
stackX.push(nextX);
stackY.push(nextY);
continue;
}
if(stackNext.peek()<4 && isSafe(nextX=x,nextY=y+1,rows,cols,matrix,flag,str,stackX.size())){
stackNext.pop();
stackNext.push(4);
stackNext.push(0);
stackX.push(nextX);
stackY.push(nextY);
continue;
}
stackNext.pop();
stackX.pop();
stackY.pop();
flag[y*cols+x] = false;
}
if(stackX.size()==str.length){
return true;
}
}
}
}
return false;
}
private boolean isSafe(int x,int y,int rows, int cols,char[] matrix, boolean[] flag,char[] str,int index){
if(str.length==index){
return true;
}
if(x<0 || y<0 || x>=cols || y>=rows){
return false;
}
if(flag[cols * y + x]){
return false;
}
if(matrix[cols * y + x]!=str[index]){
return false;
}
return true;
}
}