剑指 Offer 12. 矩阵中的路径

剑指 Offer 12. 矩阵中的路径

剑指 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

示例 2:
输入:board =
[[“a”,“b”],
[“c”,“d”]],
word = “abcd”
输出:false

提示:
1 <= board.length <= 200
1 <= board[i].length <= 200


思路

这道题,感觉还是挺难的

直观的解法:
第一步:在二维数组中,找到需要匹配字符串的第一个字母
第二步:在第一个字母的左、右、上、下找到第二个字母
如果找到则找下一个字母:
如果下一个字母为空,说明找到了
如果下一个字母不为空,则继续找
如果没有找到下一个字母:就是不匹配,回溯到上一步,上一步继续寻找

依次循环第二步

还有种思路是,纯递归
要求字符串word从[0, word.length - 1]是否满足,

如果[0, word.length - 2]不满足,返回false,则原字符数组直接返回false

如果[0, word.length - 2]满足,但word[word.length - 2]的左右上下不存在字符x == word[word.length - 1],则返回false

如果[0, word.length - 2]满足,且word[word.length - 2]的左右上下存在字符x == word[word.length - 1],但是被使用过了,则返回false

如果[0, word.length - 2]满足,且word[word.length - 2]的左右上下存在一个字符x
且字符x == word[word.length - 1],且字符x没有被使用过,那么[0, word.length - 1]就满足条件,可以返回true


难,没做出来


class Solution {
    public boolean exist(char[][] board, String word) {
        char[] words = word.toCharArray();

        // 遍历图
        for(int i = 0; i < board.length; i++) {
            for(int j = 0; j < board[0].length; j++) {

                // 如果找到了,就返回true。否则继续找
                if(dfs(board, words, i, j, 0)) return true;
            }
        }

        // 遍历结束没找到false
        return false;
    }
    boolean dfs(char[][] board, char[] word, int i, int j, int k) {
        // 判断传入参数的可行性 i 与图行数row比较,j与图列数col比较
        // i,j初始都是0,都在图左上角
        // k是传入字符串当前索引,一开始是0,如果当前字符串索引和图当前索引对应的值不相等,表示第一个数就不相等
        // 所以继续找第一个相等的数。题目说第一个数位置不固定,即路径起点不固定(不一定是左上角为第一个数)

        // 如果board[i][j] == word[k],则表明当前找到了对应的数,就继续执行(标记找过,继续dfs 下上右左)
        if(i >= board.length || i < 0 || j >= board[0].length || j < 0 || board[i][j] != word[k]) return false;
        // 表示找完了,每个字符都找到了
        // 一开始k=0,而word.length肯定不是0,所以没找到,就执行dfs继续找。
        if(k == word.length - 1) return true;   

        // 访问过的标记空字符串,“ ”是空格 '\0'是空字符串,不一样的!
        // 比如当前为A,没有标记找过,且A是word中对应元素,则此时应该找A下一个元素,假设是B,在dfs(B)的时候还是-
        // ->要搜索B左边的元素(假设A在B左边),所以就是ABA(凭空多出一个A,A用了2次,不可以),如果标记为空字符串->
        // 就不会有这样的问题,因为他们值不相等AB != ABA。 
        board[i][j] = '\0';

        // 顺序是 下 上 右 左;上面找到了对应索引的值所以k+1
        boolean res = dfs(board, word, i + 1, j, k + 1) || dfs(board, word, i - 1, j, k + 1) || 
                      dfs(board, word, i, j + 1, k + 1) || dfs(board, word, i , j - 1, k + 1);
        
        // 还原找过的元素,因为之后可能还会访问到(不同路径)
        board[i][j] = word[k];

        // 返回结果,如果false,则if(dfs(board, words, i, j, 0)) return true;不会执行,就会继续找
        return res;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值