单词搜索

123 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看活动详情

一、题目: leetcode 单词搜索 给定一个 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 仅由大小写英文字母组成

二、题解:

1.解读 要在一个由字母组成的二维数组中查找一个完整的单词,单词在字母数组中要等于上下左右相邻的元素按顺序连接的一连串元素,并且同一个位置的字母不能重复使用,最后判断字母数组中是否存在这个单词。

方法一 很明显的可以遍历递归来查找,首先单词的字母是有顺序的,按顺序来组合的元素才行,所以可以先找单词的第一个字母,遍历二维数组的元素,当找到一个等于单词第一个字母的元素时,就可以往其相邻元素继续查询单词之后的字母,如果找不到那就继续往后遍历二维数组元素,否则一直往相邻的区域扩大查找,直到找完单词的所有字母说明可以匹配就返回true,同时需要注意不能重复使用同一个位置的元素。具体的首先需要一个数组记录board数组内的元素是否使用过了,所以定义repeat数组与board数组大小一致,然后双重循环遍历board数组元素。进入到递归方法,那么递归除了需要原board数组和word单词之外。还需要一个letterIndex下标记录word单词中我们查找到哪一个字母了(初始为0),还有repeat数组就记录使用的元素下标来防止重复,ij就表示我们查找board数组中元素的下标。递归中就首先判断如果ij两个下标越界超过board数组的范围那么就肯定不存在单词需要返回false,同时当前ij位置的元素使用过了或者该元素与单词中letterIndex下标的字母不同那也是匹配不到整单词的需要返回false,然后letterIndex如果已经搜索了整个单词就说明匹配成功直接返回true了。否则的话就需要继续查找,先repeat[i][j] = true记录下当前元素正在使用了,然后就分四个上下左右方向继续往下递归查找letterIndex单词中下一个位置的字母,同样如果有一个方向的匹配成功了也可以直接返回true,否则说明当前元素开始之后组成不了单词,把repeat[i][j] = false当前元素取消占用,结束当前递归回到前面的双重循环,继续从下一个元素匹配第一个单词开始查找。

三、代码: 方法一 Java代码

class Solution {
    public boolean exist(char[][] board, String word) {
        int m = board.length;
        int n = board[0].length;
        if (m * n < word.length()) {
            return false;
        }
        boolean[][] repeat = new boolean[m][n];
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (dfs(board, word, 0, repeat, i, j)) {
                    return true;
                }
            }
        }
        return false;
    }

    private boolean dfs(char[][] board, String word, int letterIndex, boolean[][] repeat, int i, int j) {
        if (i < 0 || i >= board.length || j < 0 || j >= board[0].length) {
            return false;
        }
        if (repeat[i][j] || board[i][j] != word.charAt(letterIndex)) {
            return false;
        }
        if (letterIndex == word.length() - 1) {
            return true;
        }
        repeat[i][j] = true;
        if (dfs(board, word, letterIndex + 1, repeat, i - 1, j)) {
            return true;
        }
        if (dfs(board, word, letterIndex + 1, repeat, i + 1, j)) {
            return true;
        }
        if (dfs(board, word, letterIndex + 1, repeat, i, j - 1)) {
            return true;
        }
        if (dfs(board, word, letterIndex + 1, repeat, i, j + 1)) {
            return true;
        }
        repeat[i][j] = false;
        return false;
    }
}

时间复杂度:O(n²3^k),双重循环里面加递归。

空间复杂度:O(n²),我们需要与原数组系统的空间来记录元素是否重复。

四、总结 需要注意的就是要防止重复使用元素;还有如果一开始二维数组的所有字母都没有整个单词的字母多也就没有查找的必要了;那么同时数组中都查找到单词的字母,但是单词没有检索完所有的字母也是不匹配,但是因为我们最后判断true是要匹配完单词的所有字母,所以可以不用考虑这点。