【LeetCode】单词搜索(Word Search)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sup_chao/article/details/84871461

原题网址(中):https://leetcode-cn.com/problems/word-search/
原题网址(英):https://leetcode.com/problems/word-search/

题目:

Given a 2D board and a word, find if the word exists in the grid.
The word can be constructed from letters of sequentially adjacent cell, where “adjacent” cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once.

给定一个二维网格和一个单词,找出该单词是否存在于网格中。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

示例:
 board =
  [
    ['A','B','C','E'],
    ['S','F','C','S'],
    ['A','D','E','E']
  ]
  给定 word = "ABCCED", 返回 true.
  给定 word = "SEE", 返回 true.
  给定 word = "ABCB", 返回 false.
思路:

深搜思想,先找到起始点,然后向上下左右搜索下一个匹配点.

代码:

Prob79_word_search.java思想:
判断上/下/左/右能否移动(即移动后是否在矩阵内)→判断移动后能否与word匹配→移动(即递归)
Prob79_word_search2.java思想:
直接上/下/左/右移动(即递归)→判断移动后是否在矩阵内→判断移动后能否与word匹配

注:因为递归思路有一定差别,因此在选取起始点后的传参会有所不同。每次递归,前者判断当前(x,y)移动后匹配问题,后者判断当前(x,y) 匹配问题。因此前者起始点后调用find函数传参时,index = 1;后者index = 0.


public class Prob79_word_search {

  static boolean[][] mark;
  static int row, col;

  public static boolean exist(char[][] board, String word) {
    if (board.length == 0)
      return false;
    row = board.length;
    col = board[0].length;
    mark = new boolean[row][col];
    // find starting point
    for (int i = 0; i < row; i++)
      for (int j = 0; j < col; j++)
        if (board[i][j] == word.charAt(0))
          if (find(board, 1, word, i, j))
            return true; 
    return false;
  }

  public static boolean find(char[][] board, int index, String word, int x, int y) {
    int wordLength = word.length();
    if (index == wordLength)
      return true;
    mark[x][y] = true;
    if (x > 0) 
      if (board[x - 1][y] == word.charAt(index) && (mark[x - 1][y] == false)) 
        if (find(board, index + 1, word, x - 1, y))
          return true;
    if (y > 0) 
      if (board[x][y - 1] == word.charAt(index) && mark[x][y - 1] == false) 
        if (find(board, index + 1, word, x, y - 1))
          return true;
    if (x + 1 < row) 
      if (board[x + 1][y] == word.charAt(index) && (mark[x + 1][y] == false)) 
        if (find(board, index + 1, word, x + 1, y))
          return true;
    if (y + 1 < col)
      if (board[x][y + 1] == word.charAt(index) && (mark[x][y + 1] == false))
        if (find(board, index + 1, word, x, y + 1))
          return true;
    mark[x][y] = false;
    return false;
  }

  public static void main(String[] args) {
    char[][] board1 = {{'A', 'B', 'C', 'E'}, {'S', 'F', 'C', 'S'}, {'A', 'D', 'E', 'E'}};
    String word1 = "ABCCED";
    System.out.println(exist(board1, word1));
    String word2 = "SEE";
    System.out.println(exist(board1, word2));
    String word3 = "ABCB";
    System.out.println(exist(board1, word3));
    char[][] board2 = {{'A', 'B', 'C', 'E'}, {'S', 'F', 'E', 'S'}, {'A', 'D', 'E', 'E'}};
    String word4 = "ABCESEEEFS";
    System.out.println(exist(board2, word4));
  }
}

public class Prob79_word_search2 {

  static boolean[][] mark;
  static int row, col;

  public static boolean exist(char[][] board, String word) {
    if (board == null || board.length == 0 || board.length * board[0].length < word.length())
      return false;
    row = board.length;
    col = board[0].length;
    mark = new boolean[row][col];
    // find starting point
    for (int i = 0; i < board.length; i++)
      for (int j = 0; j < board[0].length; j++)
        if (board[i][j] == word.charAt(0))
          if (find(board, 0, word, i, j))
            return true;
    return false;
  }

  public static boolean find(char[][] board, int index, String word, int x, int y) {
    // base case 1: if exceed word's length, meaning it is done and found the word
    if (index == word.length())
      return true;

    /*
     * base case 2: if this character is out of bound or this character is not match to word's
     * character or hits character has been already visited
     */
    if (x >= row || x < 0 || y >= col || y < 0 || word.charAt(index) != board[x][y] || mark[x][y])
      return false;

    // mark this char as visited
    mark[x][y] = true;

    // follow top, right, bottom, left order to check character
    // if any direction future path return true, meaning no need to continue other directions
    if (find(board, index + 1, word, x - 1, y) || // go top
        find(board, index + 1, word, x, y + 1) || // go right
        find(board, index + 1, word, x + 1, y) || // go bottom:
        find(board, index + 1, word, x, y - 1)) // go left:
    {
      return true;
    }

    mark[x][y] = false; // clear the mark of this character

    // if this this character's all four directions path has failed, return false to last level
    return false;
  }

  public static void main(String[] args) {
    char[][] board1 = {{'A', 'B', 'C', 'E'}, {'S', 'F', 'C', 'S'}, {'A', 'D', 'E', 'E'}};
    String word1 = "ABCCED";
    System.out.println(exist(board1, word1));
    String word2 = "SEE";
    System.out.println(exist(board1, word2));
    String word3 = "ABCB";
    System.out.println(exist(board1, word3));
    char[][] board2 = {{'A', 'B', 'C', 'E'}, {'S', 'F', 'E', 'S'}, {'A', 'D', 'E', 'E'}};
    String word4 = "ABCESEEEFS";
    System.out.println(exist(board2, word4));
  }
}

猜你喜欢

转载自blog.csdn.net/sup_chao/article/details/84871461