#数据结构与算法学习笔记#剑指Offer63:矩阵中的路径 + 回溯法(Java、C/C++)

234 篇文章 1 订阅
80 篇文章 0 订阅

2019.3.4     《剑指Offer》从零单刷个人笔记整理(66题全)目录传送门​​​​​​​

以前没有做过回溯法的题目,没有经验。一开始以为是一道图的问题,开始尝试用DFS的思想做。把矩阵想象成一个稠密图,直接用矩阵存储每一个结点,在每一个点上下左右找符合的邻接点,从每一个入口结点开始进行遍历,找出所有符合输入深度的路径进行验证。这样思考貌似可以做,但是区别在于,这种用于遍历满足某一深度的所有可能路径,当题目其实给的是一条特定的路径。

其实思想已经很接近了,只要在这个遍历的基础上加入“剪枝”的思想,提前检查并排除所有不可能的路径,其实就是回溯法了。

回溯法的关键在于递归,递归的深度就是目标字符串的长度,每一层遍历都先进行检查,只走能走的路。


题目描述

请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则之后不能再次进入这个格子。 例如 a b c e s f c s a d e e 这样的3 X 4 矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。


Java实现:

/**
 * 
 * @author ChopinXBP
 * 请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。
 * 路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。
 * 如果一条路径经过了矩阵中的某一个格子,则之后不能再次进入这个格子。
 * 例如 a b c e s f c s a d e e 这样的3 X 4 矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,
 * 因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。
 *
 */


public class HasPath_64 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		char[] matrix = {'A','B','C','E','S','F','C','S','A','D','E','E'};
		char[] str = {'A','B','C','B'};
		System.out.println(hasPath(matrix, 3, 4, str));
	}

	
    public static boolean hasPath(char[] matrix, int rows, int cols, char[] str)
    {
    	if(matrix == null || str == null || str.length == 0)return false;
    	int length = matrix.length;
    	if(matrix.length == 0 || rows * cols != length || str.length > length)return false;
    	
    	boolean[] ispass = new boolean[length];
    	for(int i = 0; i < length; i++) {
    		if(Solution(i, 0, matrix, cols, str, ispass)) return true;
    	}
    	return false;
    }

    public static boolean Solution(int idx, int loc, char[] matrix, int cols, char[] str, boolean[] ispass){		    	
    	if(idx < 0 || idx >= matrix.length || matrix[idx] != str[loc] || ispass[idx]) return false;		
    	if(loc == str.length - 1)return true;
    	
    	ispass[idx] = true;
		
    	if(Solution(idx - 1, loc + 1, matrix, cols, str, ispass)
    			|| Solution(idx + 1, loc + 1, matrix, cols, str, ispass)
    			|| Solution(idx - cols, loc + 1, matrix, cols, str, ispass)
    			|| Solution(idx + cols, loc + 1, matrix, cols, str, ispass))
    		return true;
    	
    	ispass[idx] = false;	//将标志位恢复
    	return false;
    }
    
}

C++实现示例:

class Solution {
public:
    bool hasPath(char* matrix, int rows, int cols, char* str)
    {  
      if(str==NULL||rows<=0||cols<=0)
           return false;
      bool *isOk=new bool[rows*cols]();
      for(int i=0;i<rows;i++)
      {
           for(int j=0;j<cols;j++)
                if(isHsaPath(matrix,rows,cols,str,isOk,i,j))
                   return true;
      }
      return false;
    }
 bool isHsaPath(char *matrix,int rows,int cols,char *str,bool *isOk,int curx,int cury)
 {
      if(*str=='\0')
           return true;
      if(cury==cols)
      {
           curx++;
           cury=0;
      }
      if(cury==-1)
      {
           curx--;
           cury=cols-1;
      }
      if(curx<0||curx>=rows)
           return false;
      if(isOk[curx*cols+cury]||*str!=matrix[curx*cols+cury])
           return false;
      isOk[curx*cols+cury]=true;
      bool sign=isHsaPath(matrix,rows,cols,str+1,isOk,curx-1,cury)
       ||isHsaPath(matrix,rows,cols,str+1,isOk,curx+1,cury)
       ||isHsaPath(matrix,rows,cols,str+1,isOk,curx,cury-1)
       ||isHsaPath(matrix,rows,cols,str+1,isOk,curx,cury+1);
      isOk[curx*cols+cury]=false;
      return sign;
 }
};

#Coding一小时,Copying一秒钟。留个言点个赞呗,谢谢你#

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值