每日LeetCode —— 79. 单词搜索

128 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第12天,点击查看活动详情

题目描述

       给定一个m * n的网格,每个网格中放置一个英文字母,再给定一个引文单词word,请查找所给的网格中有无连续的字符可以组成一个单词与所给的单词word相同。

例1:输入:nums=[["A","B","E"],["C","A","R"],["R","E","A"]] word="ARE"  输出:true 1.png

解释:如上图所示,存在连续的字符可以组成单词"ARE"

例2:输入:nums=[["A","B","E"],["C","A","R"],["R","E","A"]] word="AN"  输出:false

解释:如上图所示,不存在连续的字符可以组成单词"AN"

本题值得注意的地方

  • 所找的字符必须为连续的。
  • 所给的网格内的元素均为英文字母

原题地址:79. 单词搜索

解题思路

       对于这种寻找符合某种规则的序列深搜是比较容易想到的。可以优化的地方是搜索的过程中进行剪枝的情况,这种情况是需要一定程度的思考才能找到。

       本题中首先我们要找到搜索的起点,即从网格中的字符与单词的首字符相同的位置开始搜索。在搜索的过程中,比较当前位置的上、下、左、右四个位置是否与当前要寻找的字母相同,如果这四个位置中某位置的字母与要找到的字符相同,则从该位置继续向下搜索,寻找单词的下一个字母。直到单词所有的字母都搜索到,即存在连续的字母与单词相同。

       为了避免环路的情况,在对上下左右每种情况进行搜索时,用flag来标识该位置是否已经搜过了。若搜索过了,则不再对该位置进行搜索,这样可避免死循环的情况。

实现代码

class Solution {
public:
    // 进行上下左右坐标变化
    int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
    // 记录结果
    bool res=false;
    void dfs(vector<vector<char>> &board,int n,int m,string &word,int i,vector<vector<bool>> &flag){
        // 如果单词所有的字母都得到了搜索,即存在字母顺序与单词相同,返回
        if(i==word.size()) {
            res=true;
            return;
        }
        // 如果已经找到一个字母的顺序与单词相同,则返回
        if(res) return ;
        // 对上、下、左、右四种情况中符合条件为位置进行搜索。
        for(int j=0;j<4;j++){
            int cn=n+dx[j],cm=m+dy[j];
            // 坐标没有超出边界且该坐标没有被搜素过,则搜索该坐标
            if(cn>=0 && cn<board.size() && cm>=0 && cm<board[0].size() && !flag[cn][cm]){
                    flag[n][m]=true;
                    if(board[cn][cm]==word[i]) dfs(board,cn,cm,word,i+1,flag);
                    flag[n][m]=false;
            }
        }
    }
    bool exist(vector<vector<char>>& board, string word) {
        vector<vector<bool>> flag(board.size(),vector<bool>(board[0].size(),false));
        // 寻找与单词首字母相同字符的位置作为搜索的起点
        for(int i=0;i<board.size();i++){
            for(int j=0;j<board[0].size();j++){
                if(board[i][j]==word[0]) dfs(board,i,j,word,1,flag);
            }
        }   
        return res;
    }
};