Welcome to Subscribe On Youtube

Question

Formatted question description: https://leetcode.ca/all/79.html

Given an m x n grid of characters board and a string word, return true if word exists in the grid.

The word can be constructed from letters of sequentially adjacent cells, where adjacent cells are horizontally or vertically neighboring. The same letter cell may not be used more than once.

 

Example 1:

Input: board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
Output: true

Example 2:

Input: board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "SEE"
Output: true

Example 3:

Input: board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCB"
Output: false

 

Constraints:

  • m == board.length
  • n = board[i].length
  • 1 <= m, n <= 6
  • 1 <= word.length <= 15
  • board and word consists of only lowercase and uppercase English letters.

 

Follow up: Could you use search pruning to make your solution faster with a larger board?

Algorithm

This question is a typical application of depth-first traversal DFS. The original two-dimensional array is like a maze. You can walk in four directions. We use each number in the two-dimensional array as a starting point to match a given string. We also need a visited array of the same size as the original array, which is of bool type to record whether the current location has been visited, because the topic requires that a cell can only be visited once.

If the current character of the two-dimensional array board is equal to the character corresponding to the target string word, then the DFS recursive function is called respectively for the four adjacent characters of the upper, lower, left, and right directions. As long as one of them returns true, then the corresponding string can be found. Otherwise it can’t be found

Code

  • 
    public class Word_Search {
    
        public class Solution {
    
            int m;
            int n;
    
            public boolean exist(char[][] board, String word) {
                m = board.length;
                n = board[0].length;
    
                boolean result = false;
    
                for (int i = 0; i < m; i++) {
                    for (int j = 0; j < n; j++) {
                        if (dfs(board, word, i, j, 0)) {
                            return true;
                        }
                    }
                }
    
                return result;
            }
    
            public boolean dfs(char[][] board, String word, int i, int j, int wordPos) {
    
                if (wordPos == word.length()) {
                    return true;
                }
    
                // @note: here, return check can remove the boundary check in each recursion, nice!
                if (i < 0 || j < 0 || i >= m || j >= n || board[i][j] != word.charAt(wordPos)) {
                    return false;
                }
    
                char temp = board[i][j];
    
                board[i][j] = '#';
    
                boolean result = ( dfs(board, word, i - 1, j, wordPos + 1)
                                || dfs(board, word, i + 1, j, wordPos + 1)
                                || dfs(board, word, i, j - 1, wordPos + 1)
                                || dfs(board, word, i, j + 1, wordPos + 1));
    
                // restore from `#`
                board[i][j] = temp;
    
                return result;
            }
        }
    }
    
    ############
    
    class Solution {
        public boolean exist(char[][] board, String word) {
            int m = board.length;
            int n = board[0].length;
            for (int i = 0; i < m; ++i) {
                for (int j = 0; j < n; ++j) {
                    if (dfs(i, j, 0, m, n, board, word)) {
                        return true;
                    }
                }
            }
            return false;
        }
    
        private boolean dfs(int i, int j, int cur, int m, int n, char[][] board, String word) {
            if (cur == word.length()) {
                return true;
            }
            if (i < 0 || i >= m || j < 0 || j >= n || board[i][j] != word.charAt(cur)) {
                return false;
            }
            board[i][j] += 256;
            int[] dirs = {-1, 0, 1, 0, -1};
            for (int k = 0; k < 4; ++k) {
                int x = i + dirs[k];
                int y = j + dirs[k + 1];
                if (dfs(x, y, cur + 1, m, n, board, word)) {
                    return true;
                }
            }
            board[i][j] -= 256;
            return false;
        }
    }
    
  • // OJ: https://leetcode.com/problems/word-search/
    // Time: O(MN * 4^K)
    // Space: O(K)
    class Solution {
    public:
        bool exist(vector<vector<char>>& A, string s) {
            int M = A.size(), N = A[0].size(), dirs[4][2] = { {0,1},{0,-1},{1,0},{-1,0} };
            function<bool(int, int, int)> dfs = [&](int x, int y, int i) {
                if (x < 0 || x >= M || y < 0 || y >= N || A[x][y] != s[i]) return false;
                if (i + 1 == s.size()) return true;
                char c = A[x][y];
                A[x][y] = 0;
                for (auto &[dx, dy] : dirs) {
                    if (dfs(x + dx, y + dy, i + 1)) return true;
                }
                A[x][y] = c;
                return false;
            };
            for (int i = 0; i < M; ++i) {
                for (int j = 0; j < N; ++j) {
                    if (dfs(i, j, 0)) return true;
                }
            }
            return false;
        }
    };
    
  • class Solution:
        def exist(self, board: List[List[str]], word: str) -> bool:
            def dfs(i, j, cur): # cur: current char count
                if cur == len(word):
                    return True
                if (
                    i < 0
                    or i >= m
                    or j < 0
                    or j >= n
                    or board[i][j] == '0'
                    or word[cur] != board[i][j]
                ):
                    return False
                t = board[i][j]
                board[i][j] = '0' # mark as visited
                for a, b in [[0, 1], [0, -1], [-1, 0], [1, 0]]:
                    x, y = i + a, j + b
                    if dfs(x, y, cur + 1):
                        return True
                board[i][j] = t
                return False
    
            m, n = len(board), len(board[0])
            return any(dfs(i, j, 0) for i in range(m) for j in range(n))
    
    ############
    
    class Solution:
      # @param board, a list of lists of 1 length string
      # @param word, a string
      # @return a boolean
      def exist(self, board, word):
        # write your code here
        if word == "":
          return True
        if len(board) == 0:
          return False
        visited = [[0] * len(board[0]) for i in range(0, len(board))]
        directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
    
        def dfs(i, j, board, visited, word, index):
          if word[index] != board[i][j]:
            return False
          if len(word) - 1 == index:
            return True
          for direction in directions:
            ni, nj = i + direction[0], j + direction[1]
            if ni >= 0 and ni < len(board) and nj >= 0 and nj < len(board[0]):
              if visited[ni][nj] == 0:
                visited[ni][nj] = 1
                if dfs(ni, nj, board, visited, word, index + 1):
                  return True
                visited[ni][nj] = 0
          return False
    
        for i in range(0, len(board)):
          for j in range(0, len(board[0])):
            visited[i][j] = 1
            if dfs(i, j, board, visited, word, 0):
              return True
            visited[i][j] = 0
        return False
    
    
  • func exist(board [][]byte, word string) bool {
    	m, n := len(board), len(board[0])
    	var dfs func(i, j, cur int) bool
    	dfs = func(i, j, cur int) bool {
    		if cur == len(word) {
    			return true
    		}
    		if i < 0 || i >= m || j < 0 || j >= n || board[i][j] != word[cur] {
    			return false
    		}
    		t := board[i][j]
    		board[i][j] = '0'
    		dirs := []int{-1, 0, 1, 0, -1}
    		for k := 0; k < 4; k++ {
    			x, y := i+dirs[k], j+dirs[k+1]
    			if dfs(x, y, cur+1) {
    				return true
    			}
    		}
    		board[i][j] = t
    		return false
    	}
    	for i := 0; i < m; i++ {
    		for j := 0; j < n; j++ {
    			if dfs(i, j, 0) {
    				return true
    			}
    		}
    	}
    	return false
    }
    
  • function exist(board: string[][], word: string): boolean {
        let m = board.length,
            n = board[0].length;
        let visited = Array.from({ length: m }, v => new Array(n).fill(false));
        for (let i = 0; i < m; ++i) {
            for (let j = 0; j < n; ++j) {
                if (dfs(board, word, i, j, 0, visited)) {
                    return true;
                }
            }
        }
        return false;
    }
    
    function dfs(
        board: string[][],
        word: string,
        i: number,
        j: number,
        depth: number,
        visited: boolean[][],
    ): boolean {
        let m = board.length,
            n = board[0].length;
        if (i < 0 || i > m - 1 || j < 0 || j > n - 1 || visited[i][j]) {
            return false;
        }
        if (board[i][j] != word.charAt(depth)) {
            return false;
        }
    
        if (depth == word.length - 1) {
            return true;
        }
    
        visited[i][j] = true;
        ++depth;
        let res = false;
        for (let [dx, dy] of [
            [0, 1],
            [0, -1],
            [1, 0],
            [-1, 0],
        ]) {
            let x = i + dx,
                y = j + dy;
            res = res || dfs(board, word, x, y, depth, visited);
        }
        visited[i][j] = false;
        return res;
    }
    
    
  • public class Solution {
        public bool Exist(char[][] board, string word) {
            var lenI = board.Length;
            var lenJ = lenI == 0 ? 0 : board[0].Length;
            var visited = new bool[lenI, lenJ];
            for (var i = 0; i < lenI; ++i)
            {
                for (var j = 0; j < lenJ; ++j)
                {
                    if (Search(board, visited, word, lenI, lenJ, i, j, 0))
                    {
                        return true;
                    }
                }
            }
            return false;
        }
    
        private int[,] paths = new int[4,2] { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };
    
        private bool Search(char[][] board, bool[,] visited, string word, int lenI, int lenJ, int i, int j, int p)
        {
            if (p == word.Length)
            {
                return true;
            }
            if (i < 0 || i >= lenI || j < 0 || j >= lenJ) return false;
            if (visited[i, j] || word[p] != board[i][j]) return false;
            visited[i, j] = true;
            for (var k = 0; k < 4; ++k)
            {
                if (Search(board, visited, word, lenI, lenJ, i + paths[k, 0], j + paths[k, 1], p + 1)) return true;
            }
            visited[i, j] = false;
            return false;
        }
    }
    
  • impl Solution {
        fn dfs(
            i: usize,
            j: usize,
            c: usize,
            word: &[u8],
            board: &Vec<Vec<char>>,
            vis: &mut Vec<Vec<bool>>,
        ) -> bool {
            if board[i][j] as u8 != word[c] {
                return false;
            }
            if c == word.len() - 1 {
                return true;
            }
            vis[i][j] = true;
            let dirs = [[-1, 0], [0, -1], [1, 0], [0, 1]];
            for [x, y] in dirs.into_iter() {
                // 索引合法性审核
                let i = x + i as i32;
                let j = y + j as i32;
                if i < 0 || i == board.len() as i32 || j < 0 || j == board[0].len() as i32 {
                    continue;
                }
                let (i, j) = (i as usize, j as usize);
                if !vis[i][j] && Self::dfs(i, j, c + 1, word, board, vis) {
                    return true;
                }
            }
            vis[i][j] = false;
            false
        }
    
        pub fn exist(board: Vec<Vec<char>>, word: String) -> bool {
            let m = board.len();
            let n = board[0].len();
            let word = word.as_bytes();
            let mut vis = vec![vec![false; n]; m];
            for i in 0..m {
                for j in 0..n {
                    if Self::dfs(i, j, 0, word, &board, &mut vis) {
                        return true;
                    }
                }
            }
            false
        }
    }
    
    

All Problems

All Solutions