[LeetCode]105. 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.

解法1:循环。先遍历整个board,找到与word[0]的匹配位置,然后以此为基准,先找出当前位置的上下左右位置与word接下来的一个字母匹配的位置,存入栈中作为待选位置。然后循环这个栈,选出其中一个位置作为此次匹配位置,以此为基准进行深度优先搜索,直至word所有字母匹配成功。

class Solution {
public:
    bool exist(vector< vector<char> >& board, string word) {
        if (board.empty() || board[0].empty() || word.empty()) return false;
        int m = board.size(), n = board[0].size(), k = word.size();
        stack< pair<int, int> > path; // 存储所有可能路径
        stack< pair<int, int> > dirc; // 存储当前位置的所有下一个候选位置
        // 循环整个board,匹配第一个字母
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                if (board[i][j] != word[0]) continue;
                int starti = i, startj = j, l = 1;
                vector<int> direction(k, 0);
                vector< vector<int> > isVisited(m, vector<int>(n, 0));
                isVisited[starti][startj] = 1;
                // 匹配接下来的所有字母
            loop:
                if (l == k) return true;
                if (startj > 0 && board[starti][startj - 1] == word[l] && isVisited[starti][startj - 1] == 0) { // left
                    dirc.push(make_pair(starti, startj - 1));
                    path.push(make_pair(starti, startj - 1));
                    ++direction[l];
                }
                if (startj < n - 1 && board[starti][startj + 1] == word[l] && isVisited[starti][startj + 1] == 0) { // right
                    dirc.push(make_pair(starti, startj + 1));
                    path.push(make_pair(starti, startj + 1));
                    ++direction[l];
                }
                if (starti > 0 && board[starti - 1][startj] == word[l] && isVisited[starti - 1][startj] == 0) { // top
                    dirc.push(make_pair(starti - 1, startj));
                    path.push(make_pair(starti - 1, startj));
                    ++direction[l];
                }
                if (starti < m - 1 && board[starti + 1][startj] == word[l] && isVisited[starti + 1][startj] == 0) { // bottom
                    dirc.push(make_pair(starti + 1, startj));
                    path.push(make_pair(starti + 1, startj));
                    ++direction[l];
                }
                while (l >= 0 && direction[l] == 0) { // 当前路径存在不匹配了,回退到最近一个分叉位置
                    l -= 1;
                    if (!path.empty()) { // 回退的那些位置需要清除访问标识
                        int idxi = path.top().first, idxj = path.top().second;
                        isVisited[idxi][idxj] = 0;
                        path.pop();
                    }
                }
                while (l >= 0 && direction[l]-- > 0) { // 当前位置的上下左右存在至少一个匹配位置,则前进继续匹配
                    ++l;
                    starti = dirc.top().first;
                    startj = dirc.top().second;
                    isVisited[starti][startj] = 1; // 标识当前位置已访问
                    dirc.pop();
                    goto loop;
                }
            }
        }
        return false;
    }
};

解法2:改用递归实现DFS。可以通过修改board当前位置字符为特定标记来降低空间复杂度为O(1)。

class Solution {
public:
    bool exist(vector< vector<char> >& board, string word) {
        if (board.empty() || board[0].empty() || word.empty()) return false;
        int m = board.size(), n = board[0].size(), k = word.size();
        vector< vector<int> > isVisited(m, vector<int>(n, 0));
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                if (search(board, word, isVisited, 0, i, j)) return true;
            }
        }
        return false;
    }
private:
    bool search(vector< vector<char> >& board, const string& word, vector< vector<int> >& isVisited, int k, int i, int j) {
        int m = board.size(), n = board[0].size();
        if (k == word.size()) return true;
        if (i < 0 || i >= m || j < 0 || j >= n || isVisited[i][j] == 1 || board[i][j] != word[k]) return false;
        isVisited[i][j] = 1;
        bool res = 
            search(board, word, isVisited, k + 1, i, j - 1) ||
            search(board, word, isVisited, k + 1, i, j + 1) ||
            search(board, word, isVisited, k + 1, i - 1, j) ||
            search(board, word, isVisited, k + 1, i + 1, j);
        isVisited[i][j] = 0;
        return res;
    }
};
原文地址:https://www.cnblogs.com/aprilcheny/p/5038474.html