• 【leetcode】Word Search II(hard)★


    Given a 2D board and a list of words from the dictionary, find all words in the board.

    Each word must 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 in a word.

    For example,
    Given words = ["oath","pea","eat","rain"] and board =

    [
      ['o','a','a','n'],
      ['e','t','a','e'],
      ['i','h','k','r'],
      ['i','f','l','v']
    ]
    

    Return ["eat","oath"].

    思路:

    好奇怪啊,我自己写了一个DFS的代码,这种TLE。网上看看发现要用字典树,其实就是把查询给定字符串的过程简化了。

    可是我的代码也查询的很容易啊。为什么我的代码TLE,字典树代码就只要56ms呢?

    字典数Trie代码:其中标记使用过字符的方式值得学习

    class Solution2 {
        class Trie{
        public:
            Trie *children[26]; //指向其子序列 从'a'到'z'
            bool leaf;  //该结点是否是叶子结点
            int idx;  //如果该节点是叶子结点, idx是该单词在vector中的序号
            Trie()
            {
                this->leaf = false;
                this->idx = 0;
                fill_n(this->children, 26, nullptr);
            }
        };
    
        public:
            void insertWords(Trie *root, vector<string>& words, int idx)
            {
                int pos = 0, len = words[idx].size();
                while(pos < len)
                {
                    if(NULL == root->children[words[idx][pos] - 'a'])
                        root->children[words[idx][pos] - 'a'] = new Trie();
                    root = root->children[words[idx][pos++] - 'a'];
                }
                root->leaf = true;
                root->idx = idx;
            }
    
            Trie * buildTrie(vector<string>& words)
            {
                Trie * root = new Trie();
                for(int i = 0; i < words.size(); ++i)
                    insertWords(root, words, i);
                return root;
            }
    
            void checkWords(vector<vector<char>>& board, int i, int j, int row, int col, Trie *root, vector<string> &res, vector<string>& words)
            {
                if(i <0 || j < 0 || i >= row || j >= col) return;
                if(board[i][j] == 'X') return; //已经访问过
                if(NULL == root->children[board[i][j] - 'a']) return;
                char temp = board[i][j];
                if(root->children[temp - 'a']->leaf) //这是叶子结点
                {
                    res.push_back(words[root->children [temp - 'a']->idx]);
                    root->children[temp - 'a']->leaf = false; //标为false表示已经找到之歌单词了
                }
                board[i][j] = 'X'; //标记这个字母为已找过
    
                checkWords(board, i-1, j, row, col, root->children[temp-'a'], res, words);
                checkWords(board, i+1, j, row, col, root->children[temp-'a'], res, words);
                checkWords(board, i, j-1, row, col, root->children[temp-'a'], res, words);
                checkWords(board, i, j+1, row, col, root->children[temp-'a'], res, words);
    
                board[i][j] = temp;
            }
    
            vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
                vector<string> res;
               int row = board.size();
               if(0==row) return res;
               int col = board[0].size();
               if(0==col) return res;
               int wordCount = words.size();
               if(0==wordCount) return res;
    
               Trie *root = buildTrie(words);
    
               int i,j;
               for(i =0 ; i<row; i++)
               {
                   for(j=0; j<col && wordCount > res.size(); j++)
                   {
                       checkWords(board, i, j, row, col, root, res, words);
                   }
               }
               return res;
            }
    
    };

    我自己的代码:

    class Solution {
    public:
        vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
            if(board.empty()) return vector<string>();
            
            vector<string> ans;    
            //对所有入口遍历
            for(int i = 0; i < board.size(); ++i)
            {
                for(int j = 0; j < board[0].size(); ++j)
                {
                    string scur;
                    unordered_set<int> myset;
                    getAnswer(i, j, board, words, scur, ans, myset);
                }
            }
            return ans;
        }
    
        void getAnswer(int i, int j, vector<vector<char>>& MyBoard, vector<string> ResWords, string scur, vector<string>& ans, unordered_set<int> myset)
        {
            if(ResWords.empty()) return; //没有更多的单词
            if(i < 0 || j < 0 || i >= MyBoard.size() || j >= MyBoard[0].size()) return;
            if(myset.find(i * MyBoard[0].size() + j) != myset.end()) return; //该字母已经使用过
            myset.insert(i * MyBoard[0].size() + j);
            vector<string> newResWords;
            //对所有剩下待匹配的单词(即前面字母都符合,并且没有完全匹配的单词)
            for(int k = 0; k < ResWords.size(); ++k)
            {
                if(MyBoard[i][j] == ResWords[k][scur.length()] && ResWords[k].length() == scur.length() + 1) //新字母与单词匹配 且单词没有更多的字母 压入答案
                    ans.push_back(scur + MyBoard[i][j]);
                else if(MyBoard[i][j] == ResWords[k][scur.length()]) //若字母匹配 压入新的剩余单词
                    newResWords.push_back(ResWords[k]);
            }
            scur += MyBoard[i][j];
    
            getAnswer(i + 1, j, MyBoard, newResWords, scur, ans, myset);
            getAnswer(i - 1, j, MyBoard, newResWords, scur, ans, myset);
            getAnswer(i, j + 1, MyBoard, newResWords, scur, ans, myset);
            getAnswer(i, j - 1, MyBoard, newResWords, scur, ans, myset);
        }
    };
  • 相关阅读:
    转载 | CSS文本溢出显示省略号
    转载 | CSS书写顺序
    转载 | CSS布局大全
    threejs sprite 制作标签
    typeScript 中的类
    Es5中的类
    typeScript中的函数
    websocket在vue项目中的使用
    typeScript中的变量数据类型
    echarts 中的1/4圆环行图的使用
  • 原文地址:https://www.cnblogs.com/dplearning/p/4516634.html
Copyright © 2020-2023  润新知