力扣第七十九题-单词搜索

478 阅读3分钟

「这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战

前言

力扣第七十九题 单词搜索 如下所示:

给定一个 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

一、思路

这一题的题目中有两个比较重要的信息:

  • 在网格 board 中选择的字符都是相邻的
  • 网格 board 中的每个字符只能选择一次

每个字符只能选择一次比较好解决,我们可以使用一个二维数组来存储该位置上的字符是否已经选择了。

那如何由相邻字符组成的单词呢?

我们可以使用递归来解决这一问题,我们定义递归的函数为:找到以网格中的 i, j 作为起点,是否能找到单词中的第 k 个元素(有四个方向:向上、向下、向左、向右)

既然想法有了,实现起来也就不苦难了。大致的步骤如下所示:

  1. 遍历网格 board
  2. 判断 board[i][j] 是否等于单词中的第一个字符,如果不想等,则继续遍历网格。如果相等,则继续判断以 i, j 为起点是否能找到单词中的下一个字符
  3. 只要能够找到一组结果就立即返回 true 即可

举个例子

此处以示例中的 board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "SEE" 作为例子

  1. 遍历网格 board
  2. i=1, j=0 时,出现了 board[1][0] = word[0]。故继续以 i=1, j=0 作为起点,无法继续匹配,故终止
  3. i=1, j=3 时,出现了 board[1][3] = word[0]
    继续以 i=1, j=3 作为起点,可找到 board[2][3] = word[1]
    再以 i=2, j=3 作为起点,可找到 board[2][2] = word[2]
  4. 最终找到了一组正确的结果,返回 true 即可

二、实现

实现代码

值得注意的是:当找到一组结果后,应立即停止,无需再寻找了,防止正确结果被更新。

    int[][] selected;
    public boolean exist(char[][] board, String word) {
        selected = new int[board.length][board[0].length];  // 初始化标志位
        for (int i=0; i<board.length; i++) {
            for (int j=0; j<board[0].length; j++) {
                if (board[i][j] == word.charAt(0)) {
                    selected[i][j] = 1;
                    if (dfs(i, j, board, 1, word)) {
                        return true;
                    }
                    selected[i][j] = 0;
                }
            }
        }
        return false;
    }


    public boolean dfs(int i, int j, char[][] board, int k, String word){
        boolean flag = false;
        if (k == word.length())
            return true;
        if (i-1 > -1 && selected[i-1][j] == 0 && word.charAt(k) == board[i-1][j]) { // 向上
            selected[i-1][j] = 1;
            flag = dfs(i-1, j, board, k+1, word);
            selected[i-1][j] = 0;
        }
        if(!flag && i+1 < board.length && selected[i+1][j] == 0 && word.charAt(k) == board[i+1][j]) {   // 向下
            selected[i+1][j] = 1;
            flag = dfs(i+1, j, board, k+1, word);
            selected[i+1][j] = 0;
        }
        if(!flag && j-1 > -1 && selected[i][j-1] == 0 && word.charAt(k) == board[i][j-1]) {  // 向左
            selected[i][j-1] = 1;
            flag = dfs(i, j-1, board, k+1, word);
            selected[i][j-1] = 0;
        }
        if(!flag && j+1 < board[0].length && selected[i][j+1] == 0 && word.charAt(k) == board[i][j+1]) {  // 向左
            selected[i][j+1] = 1;
            flag = dfs(i, j+1, board, k+1, word);
            selected[i][j+1] = 0;
        }
        return flag;
    }

测试代码

    public static void main(String[] args) {
        // board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "SEE"
        char[][] board = {{'A', 'B', 'C', 'E'}, {'S', 'F', 'C', 'S'}, {'A', 'D', 'E', 'E'}};
        char[][] board1 = {{'a', 'b'}};
        char[][] board2 = {{'C','A','A'},{'A','A','A'},{'B','C','D'}};
        boolean flag = new Number79().exist(board, "SEE");
        System.out.println(flag);
    }

结果

image.png

三、总结

感谢看到最后,非常荣幸能够帮助到你~♥

如果你觉得我写的还不错的话,不妨给我点个赞吧!如有疑问,也可评论区见~