剑指offer-矩阵中的路径

题目描述:

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

解题思路:

  1. 先查找path中的第一个字符的位置
  2. 这个位置可能有很多个,对每一个位置进行如下操作
  3. 在其周围查找下一个字符,同时将当前字符的位置信息存入数组中
  4. 如果步骤3查到了结果,查询结果是否在位置信息数组中,如果存在,退出当前循环,不存在,将结果存入数组,继续下下一个字符的查找
  5. 重复上述步骤5,直到所有循环结束。

code:

function hasPath(matrix, rows, cols, path)
{
    let Arr = matrix.split('');
    let charArr = new Array(rows);
    //初始化二维数组
    for(let i = 0 ; i < rows; i++ ){
        charArr[i] = [];
    }
    //条件判断
    if( matrix.length !== rows * cols ){
        return false;
    }
    if(path.length > matrix.length){
        return false;
    }
    //将初始值转换为二维数组
    Arr.forEach((val,index)=>{
        let y =  Math.floor(index / cols);
        let x =  index % cols;
        charArr[y][x] = val;            
    });
    
    //判断节点{x,y}是否在arr中存在
    function nodeExist(arr,{x,y}){
        for( let i = 0 ; i < arr.length; i++ ){
            if( arr[i].x === x &&  arr[i].y === y ){
                return true;
            }
        }
        return false;
    }


    //根据坐标,查找周围有没有指定的字符
    /**
     * function  根据坐标,查找周围有没有指定的字符
     * @param    {[type]}   x         [对应col]
     * @param    {[type]}   y         [对于row]
     * @param    {[type]}   charIndex [查找字符的索引]
     * @param    {[type]}   prevRes   [上一次查找后的所有节点信息]
     * @return   {[type]}             [true | false]
     */
    let findNode = function(x,y,charIndex, prevRes){		        
        let clone = [...prevRes];
        let res = false;
        if( charIndex < path.length){
            if( x + 1 < cols){
                if(hasNodeExist(x+1 ,y, charIndex, clone)){
                    return true;
                }			            
            }
            if( x - 1 >= 0){
                if(hasNodeExist(x-1 ,y, charIndex, clone)){
                    return true;
                }			           
            }
            if( y+1 < rows ){
                if(hasNodeExist(x ,y+1, charIndex, clone)){
                    return true;
                }			            
            }
            if( y-1 >= 0 ){
                if(hasNodeExist(x ,y-1, charIndex, clone)){
                    return true;
                }			            
            }
            return false;
        }else{
            return true;
        }
    }

    //第一个字符
    let firstNode = path[0];
    //在矩阵中查找第一个字符,并将结果保存起来
    let firstNodeArr = [];
    for(let i = 0 ; i < rows; i++){
        for(let j = 0 ; j < cols; j++){
            if(charArr[i][j] === firstNode ){
                firstNodeArr.push({x:j, y:i});
            }
        }
    }
		
   /**
    * function  判断在节点{x,y}是否存在charIndex位置的字符
    * @param    {[type]}   x         [col]
    * @param    {[type]}   y         [row]
    * @param    {[type]}   charIndex [路径中的字符节点位置]
    * @param    {[type]}   clone     [先前节点的位子信息]
    * @return   {Boolean}            [true | false]
    */		
    function  hasNodeExist(x,y,charIndex,clone){
        let char = path[charIndex];
        if( charArr[y][x] === char ){		
            if( !nodeExist(clone, {x:x, y:y }) ){  	                
                clone.push({x:x, y:y });			                			
                res = findNode(x, y,charIndex+1, clone );
                if(res === true){
                    return res;
                }
            }
        }
        return false;
    }

    //记录路径节点的结果
    let res = [];
    if(firstNodeArr.length === 0){
        return false;
    }else{
        for(let i = 0 ; i < firstNodeArr.length; i++){
            //从该节点开始,寻找下一个节点
            let item = firstNodeArr[i];
            let res = findNode(item.x, item.y, 1, [{x:item.x, y:item.y}]);
            if(res){
                return true;
            }
        }
        return false;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值