1. 程式人生 > 實用技巧 >0079. Word Search (M)

0079. Word Search (M)

Word Search (M)

題目

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.

Example:

board =
[
  ['A','B','C','E'],
  ['S','F','C','S'],
  ['A','D','E','E']
]

Given word = "ABCCED", return true.
Given word = "SEE", return true.
Given word = "ABCB", return false.

題意

判斷給定矩陣中是否存在一組相鄰字元序列,能夠組成目標字串。即以矩陣中一字元為起點,只能上下左右走且不能重複訪問元素,判斷有無這樣一條路徑,使起點到終點的字元序列正好組成目標字串。

思路

回溯法。


程式碼實現

Java

class Solution {
    // 控制左上右下四個方向座標的變化
    private int[] iPlus = {0, -1, 0, 1};
    private int[] jPlus = {-1, 0, 1, 0};
    private int m, n;

    public boolean exist(char[][] board, String word) {
        m = board.length;
        n = board[0].length;
        boolean[][] visited = new boolean[m][n];

        // 先找到與第一個字元相同的位置,以該位置為起點搜尋路徑
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (board[i][j] == word.charAt(0)) {
                    visited[i][j] = true;
                    if (search(board, i, j, word, 0, visited)) {
                        return true;
                    }
                    visited[i][j] = false;
                }
            }
        }
        
        return false;
    }

    private boolean search(char[][] board, int i, int j, String word, int index, boolean[][] visited) {
        if (index == word.length() - 1) {
            return true;
        }

        for (int x = 0; x < 4; x++) {
            int nextI = i + iPlus[x];
            int nextJ = j + jPlus[x];

            // 判斷鄰接點是否在矩陣內
            if (nextI < 0 || nextI >= m || nextJ < 0 || nextJ >= n) {
                continue;
            }

            // 如果鄰接點與字串中下一個字元匹配,且尚未被訪問,則繼續遞迴搜尋
            if (!visited[nextI][nextJ] && board[nextI][nextJ] == word.charAt(index + 1)) {
                visited[nextI][nextJ] = true;
                if (search(board, nextI, nextJ, word, index + 1, visited)) {
                    return true;
                }
                visited[nextI][nextJ] = false;
            }
        }
        
        return false;
    }
}

JavaScript

/**
 * @param {character[][]} board
 * @param {string} word
 * @return {boolean}
 */
var exist = function (board, word) {
  let m = board.length
  let n = board[0].length
  let visited = new Array(m).fill(0).map(v => [])
  for (let i = 0; i < m; i++) {
    for (let j = 0; j < n; j++) {
      if (board[i][j] === word[0] && dfs(board, m, n, i, j, word, 1, visited)) {
        return true
      }
    }
  }
  return false
}

let dfs = function (board, m, n, i, j, word, index, visited) {
  if (index === word.length) {
    return true
  }
  visited[i][j] = true
  let iPlus = [0, -1, 0, 1]
  let jPlus = [-1, 0, 1, 0]
  for (let x = 0; x < 4; x++) {
    let nextI = i + iPlus[x]
    let nextJ = j + jPlus[x]
    if (
      isValid(m, n, nextI, nextJ) &&
      !visited[nextI][nextJ] &&
      board[nextI][nextJ] === word[index] &&
      dfs(board, m, n, nextI, nextJ, word, index + 1, visited)
    ) {
      return true
    }
  }
  visited[i][j] = false
  return false
}

let isValid = function (m, n, i, j) {
  return i >= 0 && i < m && j >= 0 && j < n
}