算法16 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.

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值