LeetCode—剑指Offer:矩阵中的路径(DFS)

矩阵中的路径(中等)

2020年8月13日

题目来源:力扣

在这里插入图片描述

解题
这是一道经典的DFS题,个人认为创新点在于初始位置的不确定性

思路如下:
1.因为初始位置不确定,一开始要循环数组,选择初始点

2.进入DFS遍历时,判断当前坐标的字符是否与目标的字符相等,若不相等直接返回

3.题目定义可以从四个方向到下一个点,那么尝试四种方向,如果过界或已经走过的坐标就不前进,尝试前进,那就把前进点进行标识,前进后不能匹配将回溯,那么前进点设置成未标识的状态;若匹配,则不回溯,进行下一次DFS的遍历

4.DFS最终判断条件为当前步数等于目标字符串长度

  • DFS
    创建和原数组大小一致的flag数组来标记每个点是否走过,在每次进入DFS后,匹配成功则标记上这个点,匹配失败则在回溯时需要设置这个点为未标记。
    同时,因为初始位置的不确定,一开始就有个大循环,为了不让上个flag数组对之后造成影响,应该在每次找到初始点时就创建
class Solution {
    //定义函数前进的四个方向
    int[][] dxy={{0,1},{1,0},{0,-1},{-1,0}};
    //标志数组
    boolean[][] flag;
    public boolean exist(char[][] board, String word) {
        char[] words=word.toCharArray();
        int x_len=board.length;
        if(x_len==0) return false;
        int y_len=board[0].length;
        if(y_len==0) return false;
        //遍历数组
        for(int i=0;i<x_len;i++){
            for(int j=0;j<y_len;j++){
                //创建标志数组
                flag=new boolean[x_len][y_len];
                if(dfs(i,j,x_len,y_len,0,board,words)) return true;
            }
        }
        return false;
    }
    //参数:当前坐标x值,当前坐标y值,总行数,总列数,当前步数,字符数组board,字符数组words
    private boolean dfs(int cur_x,int cur_y,int total_x,int total_y,int foot,char[][] board,char[] words){
        if(board[cur_x][cur_y]!=words[foot]){
            return false;
        }
        //字符串长度相等,说明匹配成功
        if(foot==words.length-1) {
            return true;
        }
        //标记点已走过
        flag[cur_x][cur_y]=true;
        for(int i=0;i<4;i++){
            int new_x=cur_x+dxy[i][0];
            int new_y=cur_y+dxy[i][1];
            //保证不过界且未被走过
            if(new_x>=0&&new_x<total_x&&new_y>=0&&new_y<total_y&&flag[new_x][new_y]==false){
                if(dfs(new_x,new_y,total_x,total_y,foot+1,board,words)) return true;
                //回溯
                flag[new_x][new_y]=false;
            }
        }
        return false;
    }
}

在这里插入图片描述

  • DFS优化
    上个做法有个弊端就是每次都要创建flag新数组,进行优化
    我们在每次进入DFS时,都首先会判断是否与目标字符相等,那如果我暂时性的把数组的字符改成不是字母的,那在每次进入时就都会判断为不相等而返回,就相当于进行了标志。最后也要记得进行回溯,不影响之后的结果。
class Solution {
    //定义函数前进的四个方向
    int[][] dxy={{0,1},{1,0},{0,-1},{-1,0}};
    public boolean exist(char[][] board, String word) {
        char[] words=word.toCharArray();
        int x_len=board.length;
        int y_len=board[0].length;
        //遍历数组
        for(int i=0;i<x_len;i++){
            for(int j=0;j<y_len;j++){
                if(dfs(i,j,x_len,y_len,0,board,words)) return true;
            }
        }
        return false;
    }
    //参数:当前坐标x值,当前坐标y值,总行数,总列数,当前步数,字符数组board,字符数组words
    private boolean dfs(int cur_x,int cur_y,int total_x,int total_y,int foot,char[][] board,char[] words){
        if(board[cur_x][cur_y]!=words[foot]){
            return false;
        }
        //字符串长度相等,说明匹配成功
        if(foot==words.length-1) {
            return true;
        }
        //临时记录
        char temp=board[cur_x][cur_y];
        board[cur_x][cur_y]='*';
        for(int i=0;i<4;i++){
            int new_x=cur_x+dxy[i][0];
            int new_y=cur_y+dxy[i][1];
            //保证不过界
            if(new_x>=0&&new_x<total_x&&new_y>=0&&new_y<total_y){
                if(dfs(new_x,new_y,total_x,total_y,foot+1,board,words)) return true;
            }
        }
        board[cur_x][cur_y]=temp;
        return false;
    }
}

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值