剑指offer--矩阵中的路径

题目描述

请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。例如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;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值