26.单词搜索(medium)

1.题目链接:79. 单词搜索 - 力扣(LeetCode)79. 单词搜索 - 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。 示例 1:[https://assets.leetcode.com/uploads/2020/11/04/word2.jpg]输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"输出:true示例 2:[https://assets.leetcode.com/uploads/2020/11/04/word-1.jpg]输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "SEE"输出:true示例 3:[https://assets.leetcode.com/uploads/2020/10/15/word3.jpg]输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCB"输出:false 提示: * m == board.length * n = board[i].length * 1 <= m, n <= 6 * 1 <= word.length <= 15 * board 和 word 仅由大小写英文字母组成 进阶:你可以使用搜索剪枝的技术来优化解决方案,使其在 board 更大的情况下可以更快解决问题?https://leetcode.cn/problems/word-search/description/

2.题目描述:

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

true ;否则,返回 false 。​

单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂

直相邻的单元格。同一个单元格内的字母不允许被重复使用。

示例 1:​

    输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"​ 输出:true​
示例 2:​

    输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "SEE"​  输出:true​
示例 3:​

输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCB"​

     输出:false​
  提示:
     m == board.length​
     n = board[i].length​
     1 <= m, n <= 6​
     1 <= word.length <= 15​
     board 和 word 仅由大小写英文字母组成​
3. 解法:
算法思路:
我们需要假设每个位置的元素作为第一个字母,然后向相邻的四个方向进行递归,并且不能出现重复使用同一个位置的元素。通过深度优先搜索的方式,不断地枚举相邻元素作为下一个字母出现的可能性,并在递归结束时回溯,直到枚举完所有可能性,得到正确的结果。

递归函数设计:bool dfs(int x, int y, int step, vector<vector<char>>& board, string word, vector<vector<bool>>& vis, int &n, int &m, int &len)​
参数:x(当前需要进行处理的元素横坐标),y(当前需要进行处理的元素横坐标),step(当前已经处理的元素个数),word(当前的字符串状态);​
返回值:当前坐标元素作为字符串中下标 step 的元素出现是否可以找到成立的字符串。​
函数作用:判断当前坐标的元素作为字符串中下标 step 的元素出现时,向四个方向传递,查找是否存在路径结果与字符串相同。

递归函数流程:
1. 遍历每个位置,标记当前位置并将当前位置的字母作为首字母进行递归,并且在回溯时撤回标记。

2. 在每个递归的状态中,我们维护一个步数 step,表示当前已经处理了几个字母。​
                          若当前位置的字母与字符串中的第 step 个字母不相等,则返回 false。​
                          若当前 step 的值与字符串长度相等,表示存在一种路径使得 word 成立,返回 true。​

3. 对当前位置的上下左右四个相邻位置进行递归,若递归结果为 true,则返回 true。​
4. 若相邻的四个位置的递归结果都为 false,则返回 false。​

特别地,如果使用将当前遍历到的字符赋值为空格,并在回溯时恢复为原来的字母的方法,则在递归时不会重复遍历当前元素,可达到不使用标记数组的目的。

Java算法代码:

class Solution {
    boolean[][] vis;
    int m, n;
    char[] word;
    public boolean exist(char[][] board, String _word) {
        m = board.length; n = board[0].length;
        word = _word.toCharArray();
        vis = new boolean[m][n];
        for(int i = 0; i < m; i++)
            for(int j = 0; j < n; j++){
                if(board[i][j] == word[0]){
                    vis[i][j] = true;
                    if(dfs(board,i,j,1)) return true;
                    vis[i][j] = false;
                }
            }
        return false;
    }
    int []dx = {0,0,-1,1};
    int []dy = {1,-1,0,0};
    public boolean dfs(char[][] board,int i,int j,int pos){
        if(pos == word.length){
            return true;
        }
        // 上下左右去匹配 word[pos]
        // 利用向量数组,一个 for 搞定上下左右四个方向
        for(int k = 0;k<4;k++){
            int x = i +dx[k],y=j+dy[k];
            if(x >= 0 && x < m && y >= 0 && y < n && !vis[x][y] && board[x][y]== word[pos]){
                vis[x][y] = true;
                if(dfs(board,x,y,pos+1)) return true;
                vis[x][y] = false;
            }
        }
        return false;
    }
}

运行结果:

递归展开:

这里细节挺多的。

比如找所有的开始字母然后分别进行递归。

从正确开始字母,然后上下左右,都去进行遍历。

返回值的用法(和上个题目一样)。

逻辑展开:当能懂逻辑展开之后,自己进行展开,可以直接写出答案(有章法,而不是说,像是开始的时候,人脑的思考逻辑)

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

记住,相信你的递归函数,它可以做到!

记住,不理解时候,去尝试手动展开!

记住,逻辑展开(你不可能对所有的题目都进行手动展开)!

    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

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

    抵扣说明:

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

    余额充值