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;
        }
    };
  • 相关阅读:
    NX二次开发-UFUN指定原点和轴旋转视图UF_VIEW_rotate_view_abs_csys
    NX二次开发-将草图直线约束到基准轴上SketchConstraintBuilder
    NX二次开发-UFUN检验两条直线几何上是否不同UF_CURVE_LINE_ARC__is_line_equal
    C++封装DLL文件并且调用
    NX二次开发-C# NXOPEN方式多选对话框theUI.SelectionManager.SelectTaggedObjects
    NX二次开发-NXOPEN C# Part.GetPreviewImage读取prt文件预览图
    PythonOCC开发-如何搭建开发环境和一个创建圆台例子
    NX二次开发-C# NXOPEN方式单选对话框UI.GetUI().SelectionManager.SelectTaggedObject
    羊城通薅羊毛6折公交算法
    Windows DOS命令微信多开
  • 原文地址:https://www.cnblogs.com/aprilcheny/p/5038474.html
Copyright © 2011-2022 走看看