LeetCode-单词搜索(递归+回溯 )(下来反复看!认真琢磨!)

(一)题目描述

给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。

单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

(二)  解题思路

该题利用递归+回溯:

1)首先得用一个二重循环遍历二维数组中的每一个数,并以该点作为递归的起始节点

2)编写以board[i][j]为起始节点的回溯+递归函数check(board,str)以此来判断以改点为起始节点能否找到str,可以则返回true,否则返回false。

3)重点是check函数的编写。check函数中我认为的重点如下:

                (1)使用二维方向数组int[][] directions={{0,1},{0,-1},{1,0},{-1,0}}来存储遍历的四个方向                       (很实用!)

             (2)主要思路:主要是使用深度优先遍历:如果当前的board[i][j]==str[k],则向(i,j)的四个方向进行更深层次的遍历:首先是向{0,1}方向,若满足上述条件,则向(i,j+1)的四个方向再进行更深层次的遍历。若某点的四个方向均已经遍历完仍然没有满足条件的值,则回退到(i,j)的上一层,并将(i,j)点标记为false,表明该点未使用过(回溯思想)。result作用:给上层报告此条路能否走通,若能走通,则一路上去均为true,不能走通则一路上去均为false。

(三)代码如下:

class Solution26 {
    public boolean exist(char[][] board, String word) {
        int rowLen=board.length;
        int colLen=board[0].length;
        boolean f;//记录当前单词中字母所在位置
        boolean[][] flag=new boolean[rowLen][colLen];
        for (int i = 0; i <rowLen; i++) {
            for (int j = 0; j < colLen; j++) {
                //每个board[i][j]位置都要进行一次深度搜索
                f=check(board,i,j,word,flag,0);
                //如果找到一条可以通的路,则返回true,并不再继续往下找
                if(f){
                    return true;
                }
            }
        }
        return false;
    }
    //总结:涉及二维数组搜索并有方向的,最好定义一个二维数组directions=
    public boolean check(char[][] board,int i,int j,String word,boolean[][] flag,int k){
        //标记路是否走得通
        boolean result = false;
        //如果字母不相同,表示此路不通,此时递归会使函数继续找下一个方向的路
        if(board[i][j]!=word.charAt(k)){
            return false;
        }else if(k==word.length()-1){ //board[i][j]==word.charAt(k)的情况下并且是最后一个字母相等
            return true;
        }
        flag[i][j]=true;
        //标记四个方向
        int[][] directions={{0,1},{0,-1},{1,0},{-1,0}};
        for (int[] arr:directions) {
            //每一次得到新的方向
            int newi=i+arr[0];
            int newj=j+arr[1];
            if (newi>=0&&newi<board.length&&newj>=0&&newj<board[0].length){
                //如果满足以上条件,则进行搜索
                //当前这个方向以前没被搜索过
               if(!flag[newi][newj]){
                   //对newi,newj的四个方向进行搜索
                   boolean b= check(board,newi,newj,word,flag,k+1);
                   //只有当找到路之后才会返回true,所以此时若进入了if条件,说明已经成功找到路,不需要再继续向其他方向寻找了
                   if(b){
                       result=true;
                       break;
                   }
               }

            }
        }
        //退出for循环后即会执行该两条语句,此时只有两种情况:
//        (1)找到路:此时因为break而退出循环,返回的result一路向上退出递归时的返回值必定为true
//          (2)未找到路:此时因为不满足循环条件而退出循环,因为result一直为false,所以一路向上退出递归时的返回值必定为false
       flag[i][j]=false;
        return result;
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值