码迷,mamicode.com
首页 > 其他好文 > 详细

LeetCode 79. 单词搜索

时间:2021-04-14 11:52:42      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:ems   否则   简单   turn   存储   直接   出现   str   不可   

题目描述

给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

示例1:
技术图片

输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
输出:true

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/word-search

思路解析

这是一道典型的 DFS + 回溯的题目,在此记录一下 DFS 时的思路。
刚开始刷题时面对 DFS 经常感觉无从下手,后来发现写 DFS 时,不要做太多关于剪枝的考虑,先大刀阔斧地写出 DFS 的框架来,再慢慢优化算法。
DFS 的大方向主要想清楚两件事,一是下一步该去往何方,二是如何判断我是否已经抵达终点。
这两件事在这道题里都十分简单,下一步的方向就是上下左右四个格子,是否已经抵达终点可以通过判断是否已经走到了 word 的最后一位。我们可以轻易地写出如下的代码:

void dfs(int i, int j, int k) {
    visited[i][j] = true;
    if(k == word.length() - 1) {
        visited[i][j] = false;
        found = true;
        return;
    }
    for(auto p : directions) {
        int ti = i + p[0];
        int tj = j + p[1];
        if(ti < 0 || ti >= m || tj < 0 || tj >= n || visited[ti][tj] == true)
            continue;
        if(board[ti][tj] == word[k + 1]) {
            dfs(ti, tj, k + 1);
        }
    }
    visited[i][j] = false;
    return;
}

接下来是要剪枝,可以看出,虽然在一个方向上找到了结果,但是 DFS 仍然会将所有可能的路线都搜索一遍,这个过程是十分耗时的,因此我们考虑在每次判断要不要向下个方向查找时,都检查一下 found 是否已经为 true
原理上我认为这样的剪枝已经够了,但仍然可能出现超时的情况,我们需要将进一步考虑如何加速。比如,首先用哈希表存储所有在 board 中出现的字符,然后判断是否 word 中所有的字符都在 board 中出现过,若某些字符没有在 board 中出现,那是不可能找到的,因此直接返回 false 即可。

代码实现

class Solution {
private:
    vector<vector<int>> directions = {{-1, 0}, {0, -1}, {0, 1}, {1, 0}};
    string word;
    bool found = false;
    int m;
    int n;
    vector<vector<char>> board;
    vector<vector<bool>> visited;
    void dfs(int i, int j, int k) {
        visited[i][j] = true;
        if(k == word.length() - 1) {
            visited[i][j] = false;
            found = true;
            return;
        }
        for(auto p : directions) {
            int ti = i + p[0];
            int tj = j + p[1];
            if(ti < 0 || ti >= m || tj < 0 || tj >= n || visited[ti][tj] == true)
                continue;
            if(found)
                break;
            if(board[ti][tj] == word[k + 1]) {
                dfs(ti, tj, k + 1);
            }
        }
        visited[i][j] = false;
        return;
    }
public:
    bool exist(vector<vector<char>>& board, string word) {
        this->m = board.size();
        this->n = board[0].size();
        unordered_set<char> cmap;
        for(int i = 0; i < m; i++) {
            for(int j = 0; j < n; j++) {
                cmap.insert(board[i][j]);
            }
        }
        for(auto c : word) {
            if(cmap.find(c) == cmap.end())
                return false;
        }

        this->word = word;
        this->board = board;
        this->visited.assign(m, vector<bool>(n, false));
        for(int i = 0; i < m; i++) {
            for(int j = 0; j < n; j++) {
                if(board[i][j] == word[0])
                    dfs(i, j, 0);
                if(found)
                    return true;
            }
        }
        return false;
    }
};

LeetCode 79. 单词搜索

标签:ems   否则   简单   turn   存储   直接   出现   str   不可   

原文地址:https://www.cnblogs.com/xqmeng/p/14653228.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!