leetcode-79. 单词搜索

深度优先搜索(dfs)

回溯算法


题目详情

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


示例1:

1

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

示例2:

2

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

示例3:

3

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

我的代码:

不同于排列组合问题,本题采用的并不是修改输出方式,而是修改访问标记。在我们对任意位置进行深度优先搜索时,我们先标记当前位置为已访问,以避免重复遍历(如防止向右搜索后又向左返回);在所有的可能都搜索完成后,再回改当前位置为未访问,防止干扰其它位置搜索到当前位置。

class Solution 
{
public:
    void backtracking(int i, int j, vector<vector<char>>& board, string& word, bool &find, vector<vector<bool>>& visited, int pos)
    {
        if (i < 0 || i >= board.size() || j < 0 || j >= board[0].size())    //越界
        return;
        if (visited[i][j] || find || board[i][j] != word[pos])              //访问过该字母||已经找到||该字母不是所要找的
        return;
        if (pos == word.size() - 1)                                          //找够了,find置true
        {
            find = true;
            return;
        }
        visited[i][j] = true;                                               //该处字母已经访问过了
        //从该处为起点上下左右搜索
        //既然能运行到这里,那么肯定是找到了一个字母,不然上面某个语句就return了,所以pos+1
        backtracking(i + 1, j, board, word, find, visited, pos + 1);        //向下
        backtracking(i - 1, j, board, word, find, visited, pos + 1);        //向上
        backtracking(i, j+1, board, word, find, visited, pos + 1);          //向右
        backtracking(i, j-1, board, word, find, visited, pos + 1);          //向左

        visited[i][j] = false;                                              //回溯,将访问忘记
    }
    bool exist(vector<vector<char>>& board, string word) 
    {
        if (board.empty())
        return false;
        int m = board.size(), n = board[0].size();
        vector<vector<bool>> visited(m, vector<bool>(n, false));     //m*n个bool的visited
        bool find = false;                                          //初始化false
        for (int i = 0; i < m; ++i)                                 //遍历尝试每个起点
        {
            for(int j = 0; j < n; ++j)
            {
                backtracking(i, j, board, word, find, visited, 0);
            }
        }
        return find;
    }
};

涉及知识点:

1.深度优先搜索(dfs)

深度优先搜索(depth-first seach,DFS)在搜索到一个新的节点时,立即对该新节点进行遍历;因此遍历需要用先入后出的栈来实现,也可以通过与栈等价的递归来实现。对于树结构而言,由于总是对新节点调用遍历,因此看起来是向着“深”的方向前进。

2.回溯法

回溯法(backtracking)是优先搜索的一种特殊情况,又称为试探法,常用于需要记录节点状
态的深度优先搜索。通常来说,排列、组合、选择类问题使用回溯法比较方便。
顾名思义,回溯法的核心是回溯。在搜索到某一节点的时候,如果我们发现目前的节点(及
其子节点)并不是需求目标时,我们回退到原来的节点继续搜索,并且把在目前节点修改的状态
还原。这样的好处是我们可以始终只对图的总状态进行修改,而非每次遍历时新建一个图来储存
状态。在具体的写法上,它与普通的深度优先搜索一样,都有 [修改当前节点状态]→[递归子节
点] 的步骤,只是多了回溯的步骤,变成了 [修改当前节点状态]→[递归子节点]→[回改当前节点
状态]。

posted @ 2022-04-11 09:04  ggaoda  阅读(4)  评论(0编辑  收藏  举报  来源