搜索与回溯算法:DFS(深度优先搜索)

深度优先搜索:1.确定回溯终止条件2.重复生成其他可能

今天开始改用JavaScript

我的LeetCode题解:

力扣,剑指 Offer 12. 矩阵中的路径

力扣,剑指 Offer 13. 机器人的运动范围

------------------------------------

剑指 Offer 12. 矩阵中的路径

根据题目分析要找到矩阵中与word字符串第一个值相同的下标,并利用下标进行dfs匹配word字符串后面的单词是否一致。

首先有两层循环来寻找与word第一个值相等,并将i,j,k传递给dfs(k为字符串下标的当前值,默认0)

dfs函数的定义:1,先写终止条件,①i,j越界②值与word中的值不等,return false

在dfs中每获得一个下标,在对比过word后将其改为0,并用temp记录原值

如果均满足,则再次进行其他四个方向的dfs递归,将结果保存在res中,后需要对原矩阵中的字符还原值,以便如果当前符合字符串首个字母相等的情况不为最终结果,其他与首字母相等情况的递归。

code:

/**
 * @param {character[][]} board
 * @param {string} word
 * @return {boolean}
 */
var exist = function(board, word) {
    var row = board.length;//row为二维数组的行数
    var col = board[0].length;//col为二维数组的列数
    if (row*col<word.length)return false;//如果二维数组的长度没有字符长度长则直接返回false


    var dfs = function(i,j,k){//定义深度函数
        if(i<0||i>=row||j<0||j>=col||board[i][j] != word[k])return false;//递归调用的情况永远先写回溯条件
        if(k == word.length - 1)return true;//当字符为最后一个的时候并且经过上一行的判断,word已经匹配完毕,返回true
        var temp = board[i][j];//先存储一下当前的字母
        board[i][j] = '0';//定义为零是为了在上面的回溯条件使其不会走“回头路”
        var res = dfs(i+1,j,k+1)||dfs(i-1,j,k+1)||dfs(i,j+1,k+1)||dfs(i,j-1,k+1);//进行四个方向的搜索
        board[i][j] = temp;//在回溯的时候还原字母,再次寻找与word首字母相等的其他情况
        return res;
    }


    for(var i=0 ; i<row;i++){//循环获取二维数组与word第一个字符相等的i和j,
        for(var j=0;j<col;j++){
            if(board[i][j] == word[0]){
                if (dfs(i,j,0)) return true;//传递给dfs函数做回溯
            }
        }
    }
    return false;
};

剑指 Offer 13. 机器人的运动范围

最开始时如果k == 0则机器人除了本格无法去其他各自,直接返回1。
该题机器人在行走时是根据当前格子的各个位相加是否大于k来进行判断的,则需要定义一个num函数,用于计算一个数各个位相加的结果。

dfs的写法:首先所有递归的回溯都必须是先写回溯条件,本题的条件有两个:
1>:i,j不能越界(不能大于等于m,n,不能小于0)。
2>:不走之前已经走过的路,每个格子只访问一次(开始时定义一个二维数组来记录是否访问过,初始值为false,访问过后修改为true)

不满足上述条件之后,先将i,j的二维数组修改为true,代表已经走过这个位置
之后来判断机器人是否能走到这个格子,即为num(i)+num(j)<=k,如果满足则res加一,分别进行递归其他四个方向。

调用函数并且return res

根据注释简单明了

/**
 * @param {number} m
 * @param {number} n
 * @param {number} k
 * @return {number}
 */
var movingCount = function(m, n, k) {
    if(k == 0)return 1;//如果k等于0则只有第一格一个结果
    const visited = new Array(m).fill(0).map(() => new Array(n).fill(false));//新建一个二维数组并且全部为false,用于记录走过的值。
    var res = 0;//定义结果初始值为0
    var num = function(nums){//定义一个让数字各个位相加的函数
        var n = 0;
        while (nums){
            n += nums%10;
            nums = Math.floor(nums/10);//地板除法,取小
        }
        return n;
    }
    var dfs = function(i,j){//定义深度搜索函数
        if (i>=m||j>=n||i<0||j<0||visited[i][j])return;//先写回溯条件,visited数组初始值均为false
        visited[i][j] = true;//赋值为真,防止对其重复访问
        n1 = num(i);
        n2 = num(j);
        if (n1+n2<=k){//应题目要求,如果各个位相加小于k则答案加一
            res ++;
            dfs(i+1,j);//对其他四个方向进行访问
            dfs(i-1,j);
            dfs(i,j+1);
            dfs(i,j-1);
        }
    }
    dfs(0,0);//调用从0,0进行深度优先搜索
    return res;
};

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值