zoukankan      html  css  js  c++  java
  • [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;
        }
    };
  • 相关阅读:
    [LeetCode] 34. 在排序数组中查找元素的第一个和最后一个位置
    [LeetCode] 32. 最长有效括号
    [LeetCode] 31. 下一个排列
    [LeetCode] 30. 串联所有单词的子串
    [LeetCode] 29. 两数相除
    [LeetCode] 27. 移除元素
    转:畅享云时代:开发者必备的8个最佳云端集成开发环境
    转:前端集锦:十款精心挑选的在线 CSS3 代码生成工具
    转:So Easy!让开发人员更轻松的工具和资源
    转:Backbone与Angular的比较
  • 原文地址:https://www.cnblogs.com/aprilcheny/p/5038474.html
Copyright © 2011-2022 走看看