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.

解法

遇到这道题的时候,想得就是应该要用递归来进行不断的搜索,但是尝试了一下,并没有做出来。还是太渣了。

于是上网去查,看了 youtube 上花花酱的视频,理解这道题应该怎么做了。

[外链图片转存失败(img-3BkEtWxo-1567534655415)(http://ozumifmjd.bkt.clouddn.com/leetcode%2079%281%29.png)]

上面是题目给出例子的图解,起点用红色标记出来,终点用绿色,过程为黄色。

本质是一道搜索题,使用深度优先搜索更合适。因为最终要找一个唯一解,且解的长度是固定的。深度不是很大额时候,虽然 DFS 和 BFS 时间复杂度相同,但 DFS 的空间复杂度要更优。

下面是伪代码:
[外链图片转存失败(img-0UiL2WsJ-1567534655417)(http://ozumifmjd.bkt.clouddn.com/leetcode79%282%29.png)]

先找一个起点,用枚举的方式。从这个起点开始递归搜索。serach(x,y,0)表示从首字母开始搜索。

下面的 search 函数搜索第 d 个点,有三种情况:

  1. (x,y)超过格子的范围,return fasle
  2. 当前格子上的值和要找的字符不匹配,return false
  3. 当前格子上的值和要找的字符匹配,且该字符是最后一个,说明完成了,return true

剩下的还没有完成,就接着上下左右递归搜索吧。

时间复杂度

每一次都会有向四个方向的搜索,且最大深度为 l(l=len(word)),最坏情况下时间复杂度为 O( 4 l 4^l 4l)。要在起点枚举所有的可能性(格子大小为 m 行 n 列),所以整个时间复杂度为 O(mn 4 l 4^l 4l)。

而实际上不会有这么复杂,像第一个例子,只有一条路径,没有其他的分支,复杂度是线性的。

空间复杂度

空间复杂度就是其递归深度,递归了 l 层,加上初始的 m 行 n 列,总共是 O(m*n+1)

代码

花花酱的 C++代码:

class Solution {
public:
    bool exist(vector<vector<char>> &board, string word) {
        if(board.size()==0) return false;
        h = board.size();
        w = board[0].size();
        for(int i=0;i<w;i++)
            for(int j=0;j<h;j++)
                if(search(board, word, 0, i, j)) return true;
        return false;
    }

    bool search(vector<vector<char>> &board,
             const string& word, int d, int x, int y) {
        if(x<0 || x==w || y<0 || y==h || word[d] != board[y][x])
            return false;

        // Found the last char of the word
        if(d==word.length()-1)
            return true;

        char cur = board[y][x];
        board[y][x] = 0;
        bool found = search(board, word, d+1, x+1, y)
                  || search(board, word, d+1, x-1, y)
                  || search(board, word, d+1, x, y+1)
                  || search(board, word, d+1, x, y-1);
        board[y][x] = cur;
        return found;
    }
private:
    int w;
    int h;
};

python 代码:

def exist(self, board, word):
        """
        :type board: List[List[str]]
        :type word: str
        :rtype: bool
        """
       
        if len(board) == 0 or len(board[0]) == 0 or len(word)==0:return False
        for i in range(len(board)):
            for j in range(len(board[0])):
                if self.test_solution(board,i,j,0,word):return True
        return False

    def test_solution(self,board,i,j,k,word):
        if i<0 or j<0 or i>=len(board) or j>=len(board[0]) or board[i][j]!=word[k]:return False
        board[i][j] = self.token
        if k==len(word)-1:return True
        if self.test_solution(board,i-1,j,k+1,word) or self.test_solution(board,i,j-1,k+1,word) or self.test_solution(board,i+1,j,k+1,word) or self.test_solution(board,i,j+1,k+1,word):return True
        board[i][j] = word[k]
        return False

花花酱的博客
我的博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值