欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

算法16 Word Search

程序员文章站 2022-05-06 08:02:39
...

题目: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.

For example,
Given board =

[
['A','B','C','E'],
['S','F','C','S'],
['A','D','E','E']
]
word = "ABCCED", -> returns true,
word = "SEE", -> returns true,
word = "ABCB", -> returns false.
(这道题英文表述更准确些)
思路:这道题看到时,想到是去在矩阵中找,去和单词中比对,但是具体怎么做不清楚,所以学习了一哈其它人好的想法。这里我简述一个,思路具体又清晰的解法。
题目换一种说法,就类似在这个board上走path, 能不能找到这个word的path。那么我们要走path,首先要找到起点,先遍历board,把和word的第一个字母一样的都当作起点代入我们的递归function。我们要记录每一个点的位置,所以要列和行;我们要记录word中的字母,所以要一个wordIndex;最重要的是,我们需要判断,哪些点我们已经走过了,所以要一个boolean markBoard[][];对于起点(每一个点),最基本的思路是,可以走四个方向,把那个方向的下一个点继续递归,只要有一条path 成功了,返回回来就可以直接return了,不需要继续把所有的pathes 都看完;对于每一个点,要检查 1, word 是否已经找到了 return true; 还要检查 2,这个点是否可以探索(比如这个点超出board范围了,它和word中的char不相等,它已经被探索过了), return false。

复杂度
时间 O(N^2) 空间 O(N)

代码:

public boolean exist(char[][] board, String word) 
{
    if(board == null || board.length == 0 
            || board.length * board[0].length < word.length())
        return false;
    
    boolean[][] mark = new boolean[board.length][board[0].length];
    boolean res = false;
    //遍历board, 找出与word的第一个字母相同的,开始找path
    for(int i=0; i<board.length; i++)
    {
        for(int j=0; j<board[0].length; j++)
        {
            if(board[i][j] == word.charAt(0))
                res = res || findWord(board, word, 0, i, j, mark);
            
            if(res)
                return res;
        }
    }
    
    return res;
}

public boolean findWord(char[][] board, String word, int wordIndex, 
        int row, int col, boolean[][] markBoard)
{
    // 如果wordIndex等于word.length(),说明已经找到了path
    if(wordIndex == word.length())
        return true;
    
    /* 如果已经超出了board界限,
     * 或者word的字母不等于该位置的字母
     * 或者这个位置已经走过了
        */
    if(row >= board.length || row < 0 ||  col >= board[0].length || col < 0
            || word.charAt(wordIndex) != board[row][col] || markBoard[row][col])
        return false;
    
    
    // 记录下这个位置走过了
    markBoard[row][col] = true;
    
    // 从上下左右顺序检查字母
    // 如果任何方向的未来路径都是正确的,意味着不需要继续其他方向
    if(findWord(board, word, wordIndex + 1, row - 1, col, markBoard) || // go top
       findWord(board, word, wordIndex + 1, row, col + 1, markBoard) || // go right
       findWord(board, word, wordIndex + 1, row + 1, col, markBoard) || // go bottom:
       findWord(board, word, wordIndex + 1, row, col - 1, markBoard))   // go left:
    {
        return true;
    }
    
    markBoard[row][col] = false; // 清除这个位置的记录

    //这个字符的四个方向都失败了,返回到最后一个级别
    return false;
}