剑指offer js算法练习(65-66)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_37473645/article/details/85109836

目录

回溯法

65.矩阵中的路径

66.机器人的运动范围


回溯法

        回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。

        通常回溯法算法适合用递归实现代码。

65.矩阵中的路径

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

        时间限制:1秒 空间限制:32768K

分析:这是一个可以用回溯法解决的典型题。首先,在矩阵中任选一个格子作为路径的起点。假设矩阵中某个格子的字符为c,并且这个字符将对应路径上的第i个字符。如果路径上的第i个字符与这个格子的字符不相等,则说明这个格子不是处于路径上的第i个位置。如果路径上的第i个字符与这个格子的字符相等,那么就可以去与这个格子相邻的格子上去找路径上的第i+1个位置。除矩阵边界上的格子之外,其他格子都有4个相邻的格子。重复这个过程,直到路径上的所有字符都在矩阵中找到相应的位置。

function hasPath(matrix, rows, cols, path){
    if(matrix==undefined||rows<=0||cols<=0||path.length<0){
        return false;
    }
    var visited=new Array();
    for(var i=0;i<rows*cols;i++){
        visited[i]=false;
    }
    var pathLength = 0;
    for(var row = 0; row < rows; ++row){
        for(var col = 0; col < cols; ++col){
            if(hasPathCore(matrix, rows, cols, row, col, path,
                           pathLength, visited))
            {
                return true;
            }
        }
    }

    visited.length=0;

    return false;
}
function hasPathCore(matrix,rows,cols,row,col,path,pathLength,visited){
    if(path.length == pathLength){
        return true;
    }
    var hasPath=false;
    if(row >= 0 && row < rows && col >= 0 && col < cols
           && matrix[row * cols + col] == path[pathLength]
           && !visited[row * cols + col]){
        pathLength++;
        visited[row*cols+col]=true;
        hasPath=hasPathCore(matrix,rows,cols,row,col-1,
                            path,pathLength,visited)
        ||hasPathCore(matrix,rows,cols,row-1,col,
                      path,pathLength,visited)
        ||hasPathCore(matrix,rows,cols,row,col+1,
                      path,pathLength,visited)
        ||hasPathCore(matrix,rows,cols,row+1,col,
                      path,pathLength,visited);
        if(!hasPath){
            --pathLength;
            visited[row * cols + col] = false;
        }
    }
    return hasPath;
}

66.机器人的运动范围

        地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?

        时间限制:1秒 空间限制:32768K

分析:和上一道题类似,这个方格也可以看作一个mxn的矩阵,同样,在这个矩阵中,除边界上的格子之外,其他格子都有4个相邻的格子。机器人从坐标(0,0)开始移动。当它准备进入坐标为(i,j)的格子时,通过检查坐标的位数的和来判断机器人是否能够进入。如果机器人能够进入坐标为(i,j)的格子,则再判断机器人能否进入4个相邻的格子(i-1,j),(i,j-1),(i+1,j),(i,j+1)。因此可以用如下代码来实现回溯算法:

function movingCount(threshold, rows, cols){
    if(threshold<0||rows<=0||cols<=0){
        return 0;
    }
    var visited=new Array();
    for(var i=0;i<rows*cols;i++){
        visited[i]=false;
    }
    var count=movingCountCore(threshold,rows,cols,0,0,visited);
    delete visited;
    return count;
}
function movingCountCore(threshold,rows,cols,row,col,visited){
    var count=0;
    if(check(threshold,rows,cols,row,col,visited)){
        visited[row*cols+col]=true;
        count=1+movingCountCore(threshold,rows,cols,row-1,col,visited)
        +movingCountCore(threshold,rows,cols,row,col-1,visited)
        +movingCountCore(threshold,rows,cols,row+1,col,visited)
        +movingCountCore(threshold,rows,cols,row,col+1,visited);
    }
    return count;
}
function check(threshold,rows,cols,row,col,visited){
    if(row>=0&&row<rows&&col>=0&&col<cols&&
       getDigitSum(row)+getDigitSum(col)<=threshold
       &&!visited[row*cols+col])
        return true;
    return false;
}
function getDigitSum(number){
    var sum=0;
    while(number>0)
    {
        sum+=number%10;
        number=Math.floor(number / 10);
    }
    return sum;
}

猜你喜欢

转载自blog.csdn.net/qq_37473645/article/details/85109836