2.4.3 回溯法

面试题12:矩阵中的路径

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

主要思想:

  • 一个一维数组visited用于存储格子中的数字是否被访问过,主方法遍历每一个格子,去判断这个格子能否获取到路径(另一个方法,该格子能获取到路径,返回true)。
  • 获取路径的方法hasPathCore,判断当前的格子的内容是否和路径的当前未访问过的第一个字符相同,并且当前格子没有被访问过,如果为true,路径的当前索引+1,设置当前格子被访问,然后去递归查找该格子的上下左右格子有没有路径,如果没有找到路径,说明以当前格子开头失败,所以回退,设置路径的索引-1,设置当前格子没有被访问过。最后返回是否找到路径的bool值。
<script>
    //matrix是一个一维数组,path是路径字符串

    function hasPath(matrix, rows, cols, path)
    {
        if(matrix==null||rows<1||cols<1||path==null)
            return false;
        // write code here
        //用数组存元素是否被访问过,访问过的就不能再访问了,数组的大小就是行*列
        let visited=new Array(rows*cols);
        //用来保存path字符串的索引
        let pathIndex=0;
        //通过遍历每个各自,判断是否能找到路径
    for(let row=0;row<rows;row++){
        for(let col=0;col<cols;col++){
            //如果这个格子能够找到路径就会返回true
            if(hasPathCore(matrix,rows,cols,row,col,visited,pathIndex,path))
                return true;
        }
    }
        return false;
    }
    //判断这个格子作为起点能不能构成path
    function hasPathCore(matrix,rows,cols,row,col,visited,pathIndex,path){
        //如果pathIndex已经是path的长度了,说明已经构成了path,返回true。
        if(pathIndex===path.length)
            return true;
        let haspath=false;
        //如果这个格子和路径中pathIndex值相同,并且这个格子没有被访问过,表示找到了
        if(row>=0&&row<rows&&col>=0&&col<cols&&matrix[row*cols+col]===path[pathIndex]&&!visited[row*cols+col])
        {
            //给pathIndex++
            pathIndex++;
            //设置这个格子被访问过
            visited[row*cols+col]=true;
            //递归的在左右上下格子查找路径
            haspath=hasPathCore(matrix,rows,cols,row-1,col,visited,pathIndex,path)||
                hasPathCore(matrix,rows,cols,row+1,col,visited,pathIndex,path)||
                hasPathCore(matrix,rows,cols,row,col-1,visited,pathIndex,path)||
                hasPathCore(matrix,rows,cols,row,col+1,visited,pathIndex,path);
            //如果找不到,这个格子作为起点就不行,就当作没有用过,这条路径不通
            if(!haspath){
                pathIndex--;
                visited[row*cols+col]=false;
            }
        }

        return haspath;

    }
</script>

面试题13:机器人的运动范围
其实这一题并没有回溯

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

主要思想:从0.0点开始,用一个数组去存格子是否被访问过,然后判断这个格子是否满足条件,如果满足,
设置格子被访问过,递归求count=1+上下左右可到达的格子数。

<script>
    function movingCount(threshold, rows, cols) {
        if(threshold==null||rows<=0||cols<=0)
            return false;
        //定义一个数组用于存储格子是否被访问过
        let visited=new Array(rows*cols).fill(false);
        //方法返回所有的格子数
        return moveingCountCore(threshold, rows, cols, 0, 0, visited);
    }


    //从0,0点开始,格子数就是1+当前格子上下左右格子的
    function moveingCountCore(threshold, rows, cols, row, col, visited) {
        let count=0;
        //检查当前格子是否可达,是否满足坐标位数之和小于k
        if(check(threshold, rows, cols, row, col, visited)){
            //如果是,就将格子设置为已经被访问
            visited[row*cols+col]=true;
            //对于这个格子的可访问格子数就是上下左右可访问格子数之和
            count=1+moveingCountCore(threshold, rows, cols, row-1, col, visited)+
                moveingCountCore(threshold, rows, cols, row+1, col, visited)+
                moveingCountCore(threshold, rows, cols, row, col-1, visited)+
                moveingCountCore(threshold, rows, cols, row, col+1, visited);

        }
        return count;
    }



    function check(threshold, rows, cols, row, col, visited) {

        return row >= 0 && row < rows && col >= 0 && col < cols && getDigitSum(row) + getDigitSum(col) <= threshold &&
            visited[row * cols + col] === false;
    }

    function getDigitSum(number) {
       let str=number.toString();
       let sum=0;
       for(let i=0;i<str.length;i++){
           sum=sum+parseInt(str[i]);
       }
       return sum;
    }
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,185评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,652评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,524评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,339评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,387评论 6 391
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,287评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,130评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,985评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,420评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,617评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,779评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,477评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,088评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,716评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,857评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,876评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,700评论 2 354

推荐阅读更多精彩内容