• [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;
        }
    };
  • 相关阅读:
    Android笔记:数据储存
    Android笔记:管理所有活动
    Android随笔:属性
    Android笔记:限定符
    Android笔记:ninepatch
    Android笔记:获取屏幕信息
    js自动完成
    动态生成实体类
    EF框架学习手记
    js遮罩效果
  • 原文地址:https://www.cnblogs.com/aprilcheny/p/5038474.html
Copyright © 2020-2023  润新知