zoukankan      html  css  js  c++  java
  • 【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);
        }
    };
  • 相关阅读:
    十个男人看了,九个成了富人
    win7下编译安装osgearth
    gdal源码编译安装
    win7下编译boost库总结
    everything && executor
    cursor:hand与cursor:pointer的区别介绍
    web程序记录当前在线人数
    汉字转拼音
    40多个非常有用的Oracle 查询语句
    asp.net 使用IHttpModule 做权限检查 登录超时检查(转)
  • 原文地址:https://www.cnblogs.com/dplearning/p/4516634.html
Copyright © 2011-2022 走看看