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。此题本质是寻找路径,即在无向图中寻找指定的路径——将每一个元素看成图中节点,上下左右的元素看成节点的邻接节点。即本题需要在图中验证是否存在沿着给定word路径走的线路。这里需要注意的是,传统的DFS只需要完成所有节点的访问即可知道是否存在某一符合要求的通路,而此题在寻找通路的过程中是允许对“岔路节点”的重复访问的。原因是,当DFS到一个节点,如果这个节点有多个邻接节点都满足给定路径的下一个节点要求,那么如果其中一条路径不满足最后总路径要求,我们还需要回溯到岔路节点来验证另一条从这个节点出发的岔路是否满足余下路径的要求。所以,这相当于在DFS中增加了回溯,即我们要记录每一个岔路节点,之后验证其之后的路径,验证完毕之后要将岔路节点回溯到原来的状态,以便进行其他岔路的判断。由于我们要记录岔路节点,那么其实可以将岔路节点设置成一个特殊字符,这样省去了一个二维的visited boolean数组,节省了一些空间。

 


Java

class Solution {
    public boolean exist(char[][] board, String word) {
        if (board == null || board.length == 0 || board[0].length == 0) return false;
        if (word.length() == 0) return true;        
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[0].length; j++) {
                int p = 0;
                if (word.charAt(0) == board[i][j])
                    if (dfs(board, i, j, word, p)) return true;   
            } 
        }
        return false;
    }
    
    private boolean dfs(char[][] board, int i, int j, String word, int p) {
        if (p == word.length()) return true;
        if (i >= board.length || i < 0 || j >= board[0].length || j < 0 || board[i][j] != word.charAt(p)) return false;
        char temp = word.charAt(p);
        board[i][j] = '*';
        boolean flag = dfs(board, i, j+1, word, p+1) || dfs(board, i, j-1, word, p+1) || dfs(board, i+1, j, word, p+1) || dfs(board, i-1, j, word, p+1);
        board[i][j] = temp;
        return flag;      
    }
}

 

posted on 2018-08-29 10:41  小T在学习  阅读(329)  评论(0编辑  收藏  举报