LeetCode 79. 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.

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.

这道题也是一道典型的DFS的题,要求从一个二维的字符矩阵中查找一个单词是否存在。虽然知道是DFS但我还是菜到不会写代码,看了下上次写的num of island也还是不会写,于是就去看了答案,终于大概又懂了点套路。

首先还是按行和列遍历整个矩阵,对于每个元素采用DFS,如果能从这个元素找到一个合适的路径就返回true。重点就在于这个DFS函数,正常的DFS函数的参数至少要包括这个board和row、col index,由于我们这里还需要查找字符是否在字符串中,于是也需要把这个string传进去,并且需要知道它的位置是否对应,因此还需要加入一个index,表明现在在查询的是字符串中的第index个字符。在DFS函数中,首先检查直接返回true/false的情况,false对应着当前的坐标越界了或者这个格子的字符不是当前需要查找的字符,true的情况对应着当前格子的字符是word中的最后一个字符。如果不是以上两种情况,那么我们就需要继续进行DFS。这里需要将当前的格子标记为visited,以防形成死循环,可以采用先将这个格子变成*的方式。然后我们就可以对这个格子的上下左右四个方向进行遍历,并将四个方向的结果取或作为以当前这个格子为起始的字符串的遍历结果。在四个方向遍历以后,需要将这个格子标记的visited也就是*转换成原来的样子,否则会影响后面的遍历。

代码的时间复杂度据说是O(M * N * 4^L),其中M是row,N是col,L是word的长度,空间复杂度是O(L)。来源:https://leetcode.com/problems/word-search/discuss/27658/Accepted-very-short-Java-solution.-No-additional-space.

Since no one is talking about the complexity. I think space is O(L) where L is the length of the word; and time is O(M * N * 4^L) where M*N is the size of the board and we have 4^L for each cell because of the recursion. Of course this would be an upper bound. Not sure if it is good enough in an interview.

提交了代码发现时间272ms,31.57%,空间154.9M,35.29%。感觉大家方法都一样啊怎么我这个跑出来的结果那么差,疑惑.jpg

代码如下:

class Solution {
public:
    bool dfs(vector>& board, int i, int j, string word, int index) {
        if (i < 0 || i >= board.size() || j < 0 || j >= board[0].size() || board[i][j] != word[index]) {
            return false;
        }
        
        if (index == word.size() - 1) {
            return true;
        }
        
        char temp = board[i][j];
        board[i][j] = '*';
        bool find = dfs(board, i + 1, j, word, index + 1) || 
                    dfs(board, i - 1, j, word, index + 1) || 
                    dfs(board, i, j + 1, word, index + 1) || 
                    dfs(board, i, j - 1, word, index + 1);
        board[i][j] = temp;
        
        return find;
    }
    
    bool exist(vector>& board, string word) {
        int rows = board.size();
        int cols = board[0].size();
        if (rows == 0 || cols == 0) {
            return false;
        }
        
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                if (dfs(board, i, j, word, 0)) {
                    return true;
                }
            }
        }
        
        return false;
    }
};

DFS的递归函数其实还有另一种和之前的num of islands相似的写法。先定义好result=false,然后在每一次dfs的时候先判断它是不是越界了并且还没找到答案(result=false),但感觉这样好像不如上面这种写法直观。贴个这种写法的链接:https://leetcode.com/problems/word-search/discuss/27739/My-DFS-%2B-Backtracking-C%2B%2B-solution-(16ms)

你可能感兴趣的:(LeetCode)