剑指 Offer 12. 矩阵中的路径

题目描述

请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一格开始,每一步可以在矩阵中向左、右、上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。例如,在下面的3×4的矩阵中包含一条字符串“bfce”的路径(路径中的字母用加粗标出)。

[[“a”,“b”,“c”,“e”],
[“s”,“f”,“c”,“s”],
[“a”,“d”,“e”,“e”]]

但矩阵中不包含字符串“abfb”的路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入这个格子。

示例 1:
输入:board = [[“A”,“B”,“C”,“E”],[“S”,“F”,“C”,“S”],[“A”,“D”,“E”,“E”]], word = “ABCCED”
输出:true

提交的代码

参考这个视频
https://www.bilibili.com/video/BV1ZK4y1b7Xn?p=10

public class ArrayPath {
    public static void main(String[] args) {
        char[][]board={{'a','b','c','d'},
                {'g','f','g','h'},
                {'i','j','i','l'},
                {'e','n','o','p'}};
       String word="bfgie";
        System.out.println(exist(board, word));
        // char[][]board={{'a','b'},{'c','d'}};
//        Solution sl=new Solution();
//        System.out.println(sl.exist(board, "ojf"));
    }
     static boolean exist(char[][]board,String word)
     {
         for(int i=0;i<board.length;i++)
         {
             for(int j=0;j<board[0].length;j++)
             {
                 if(dfs(board,word,0,i,j))
                     return true;
             }
         }
         return false;
     }
     static boolean dfs(char[][]board,String word,int u,int x,int y)
     {
        //先判断下标,后判断元素
        if(x<0||x>board.length-1||y<0||y>board[0].length-1||board[x][y]!=word.charAt(u))
        {
            return false;//数组越界或者没有找到word中的相应的字符就返回false
        }
        if(u==word.length()-1)//表示已经查找到word的最后一个字符,说明整个字符串都被找到,刚传进来时u是0,所以不可能进来就返回
        {
            return true;
        }
        char temp=board[x][y];
        board[x][y]='*';//用过的字符就做一个标记,下次不再使用,因为前面已经判断过board[x][y]=word.charAt(u),说明此时的board[x][y]符合要求
        boolean  res=dfs(board,word,u+1,x-1,y)
                || dfs(board,word,u+1,x+1,y)
                ||dfs(board,word,u+1,x,y+1)
                ||dfs(board,word,u+1,x,y-1);
        board[x][y]=temp;//每回溯完一次要把board[x][y]还原
        /*
        递归搜索匹配字符串过程中,需要 board[i][j] = '*' 来防止 ”
        走回头路“ 。当匹配字符串不成功时,会回溯返回,此时需要
        board[i][j] = tmp 来”取消对此单元格的标记”。 在DFS过程中
        ,每个单元格会多次被访问的, board[i][j] = '*'只是要保证在
        当前匹配方案中不要走回头路。
        */

 return res;
     }
}
/*
整个代码的执行流程是首先在二维数组中遍历找到word的第一个字符对应的i,j,先传进来dfs(board,word,0,i,j)
注意,这是考虑了二维数组中有多个word的第一个字符的情况的,只是当其中一种能够不满足时,就接着找下一组
当其中一组满足时,就return true,如果二维数组遍历完,没有找到合适的路径,则返回false
dfs(board,word,0,i,j),进来先判断边界条件,以及board[x][y]==word.charAt(u)),刚开始进来的时候肯定是满足这个条件的
在我看来,这些限制条件都是给递归设定的出口
当满足边界条件以及board[x][y]==word.charAt(u)),接下来就是判断现在的u是否达到word的最后一个字符
如果是,则说明整个字符串被找到,返回true,如果不是,说明我们还需要接着找,先把当前的这个点做一个标记,
因为题目限定如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子
接着找就有上下左右查找4种选择,或运算||的规则是其中一个条件满足就返回true

 */

在这里插入图片描述在这里插入图片描述

在这里插入图片描述

自己写的有错的代码

import java.util.HashMap;
import java.util.Map;

public class pathInArray {
    public static void main(String[] args) {
        char[][]board={{'a','b','c','d'},
                       {'e','f','g','h'},
                       {'i','j','k','l'},
                       {'m','n','o','p'}};
       // char[][]board={{'a','b'},{'c','d'}};
        Solution sl=new Solution();
        System.out.println(sl.exist(board, "ojf"));
    }
}
class Solution {
    int cur_row=0;//全局变量,记录假如查找到word中的一个字符之后,行的位置
    int cur_col=0;//全局变量,记录假如查找到word中的一个字符之后,列的位置
    char c=' ';//全局变量,用来判断每次dfs返回的值
    int [][]assist_board;//辅助矩阵标记用过的格子
    int count_f=0;
    char a;
    public boolean exist(char[][] board, String word) {
        int i = board.length;
        int j = board[0].length;
        assist_board=new int [i][j];//初始化
        int word_length = word.length();
        HashMap<Integer, Integer> positionOfFirstChar = new HashMap<>();//存放第一个字符在矩阵中的位置

        if (i == 0)
            return false;

        //先找到第一个字符在矩阵中的位置
        for (int m = 0; m < i; m++) {

            for (int n = 0; n < j; n++) {
                if (board[m][n] == word.charAt(0)) {
                    positionOfFirstChar.put(m, n);
                }
            }
        }
        if (positionOfFirstChar.isEmpty()) {
            return false;//连第一个字符都没有,返回false
        }
        for (Map.Entry<Integer, Integer> entry : positionOfFirstChar.entrySet()) {//遍历第一个字符的位置,其中一种情况能够满足找到出入的字符,就break

            for (int p = 0; p < word_length - 1; p++) {
                // char ac=word.charAt(p);
                a=dfs(board,  entry.getKey(), entry.getValue(), word.charAt(p), word.charAt(p + 1));//传入指针当前位置,p是已经查找到的字符
                //q是p的下一个字符
                if(a=='f')
                {
                    count_f++;
                    break;
                }

            }
            if(count_f==0)
            {
                return true;
            }
           // return true;//第一个字符所在位置的其中一种情况满足就返回true,都不满足则返回false
        }
        return false;
    }

//        for(int m=0;m<i;m++)
//        {
//
//            for(int n=0;n<j;n++)
//            {
//
//            }
//        }
        //return false;

    char dfs(char[][] board,int i,int j,char p,char q)
    {
        int board_row=board.length;
        int board_col=board[0].length;
//        if(board[i][j]==p&&assist_board[i][j]==0)//查找到指定字符,且该点还没有用过
//        {
//            assist_board[i][j]=1;//一旦用过,就置1,默认是0
//            cur_row=i;
//            cur_col=j;
//           // return true;
//        }

        if(board[i][j]==q&&assist_board[i][j]==0)//查找到指定字符,且该点还没有用过
        {
            assist_board[i][j]=1;//一旦用过,就置1,默认是0
            cur_row=i;
            cur_col=j;
            return 'o';
        }
        if(c!=q)
        {
            return 'a';
        }

        if(i-1>=0&&i-1<=board_row-1&&j>=0&&j<=board_col-1&&assist_board[i-1][j]!=1)//向上找
        {
            c=dfs( board, i-1,j, p,q);
        }
         if(i+1>=0&&i+1<=board_row-1&&j>=0&&j<=board_col-1&&assist_board[i+1][j]!=1)//向下找
        {
            c= dfs( board, i+1,j, p,q);
        }
         if(i>=0&&i<=board_row-1&&j+1>=0&&j+1<=board_col-1&&assist_board[i][j+1]!=1)//向右找
        {
            c= dfs( board, i,j+1, p,q);
        }
         if(i>=0&&i<=board_row-1&&j-1>=0&&j-1<=board_col-1&&assist_board[i][j-1]!=1)//向左找
        {
            c=dfs( board, i,j-1, p,q);
        }
//        else
//            return false;
        if (c!=q)
        {
            return 'f'; //表示找到了q,且q在p的上下左右其中一个位置
        }
        else
            return 'o';
    }


}
//怎么保证连续呢,就是查找abc的话,先查找到a要保证b出现在a的上下左右方位其中一个呀?
//想法:传参的时候就把a的下一个字符也传进去

//应该先遍历矩阵,找到第一个字符所在的位置,如果有重复,可以用Map来存
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值