zoukankan      html  css  js  c++  java
  • LeetCode-212 Word Search II

    题目描述

    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.

    题目大意

    给定一个二维数组,数组中包含小写字母,同时给一个字符串数组,数组中每个字符串为一个单词,要求查找出在字符串数组中出现的,并且能在二维数组拼接出来的单词(在二维数组中,当两个字母上下左右拼接在一起时可以组成一个单词的序列)。

    示例

    E

    Input: 
    board = [
      ['o','a','a','n'],
      ['e','t','a','e'],
      ['i','h','k','r'],
      ['i','f','l','v']
    ]
    words = ["oath","pea","eat","rain"]

    Output: ["eat","oath"]

    解题思路

    根据LeetCode@rabeeh的思路,需要建立一个Trie结构的树(Trie结构如题LeetCode - 211所述),即该树保存了字符串数组中所有单词的前缀表示。并遍历二维数组中的每一个位置,在每个位置开始进行树节点查找,查找符合条件的单词并加入结果集合中。

    复杂度分析

    时间复杂度:O(|V| + |E|)

    空间复杂度:O(|V| + |E|)

    代码

    //树结点结构
    class TrieNode {
    public:
        bool end;
        vector<TrieNode*> children;
        
        TrieNode() {
            end = false;
            children = vector<TrieNode*>(26, NULL);
        }
    };
    
    class Trie {
    public:
        //树的初始化,为每个单词建立一个树的从根节点到叶节点的路径
        Trie(vector<string>& words) {
            root = new TrieNode();
            for(string word : words) {
                addNode(word);
            }
        }
        
        TrieNode* getRoot() {
            return root;
        }
        
        void addNode(string word) {
            TrieNode* cur = root;
            for(int i = 0; i < word.length(); ++i) {
                if(!cur->children[word[i] - 'a']) {
                    cur->children[word[i] - 'a'] = new TrieNode();
                }
                cur = cur->children[word[i] - 'a'];
            }
            cur->end = true;
        }
        
    private:
        TrieNode* root;
    };
    
    class Solution {
    public:
        vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
            Trie* tree = new Trie(words);
            TrieNode* root = tree->getRoot();
            unordered_set<string> res;
            //以二维数组中的当前位置为单词的起始字母进行查找
            for(int i = 0; i < board.size(); ++i) {
                for(int j = 0; j < board[0].size(); ++j) {
                    find(board, root, res, i, j, "");
                }
            }
            
            vector<string> ans;
            for(auto iter = res.begin(); iter != res.end(); ++iter)
                ans.push_back(*iter);
            
            return ans;
        }
        
        void find(vector<vector<char> >& board, TrieNode* node, unordered_set<string>& res, int x, int y, string word) {
            //若访问位置越界或该位置已被访问则返回
            if(x < 0 || x >= board.size() || y < 0 || y >= board[0].size() || board[x][y] == ' ')
                return;
            
            if(node->children[board[x][y] - 'a'] != NULL) {
                char c = board[x][y];
                word += c;
                board[x][y] = ' ';
                //若当前节点是某个单词的结尾,则代表可以找到一个符合条件的单词
                if(node->children[c - 'a']->end)
                    res.insert(word);
                //依次查找二维数组的四个方向,进行递归遍历
                find(board, node->children[c - 'a'], res, x - 1, y, word);
                find(board, node->children[c - 'a'], res, x, y + 1, word);
                find(board, node->children[c - 'a'], res, x + 1, y, word);
                find(board, node->children[c - 'a'], res, x, y - 1, word);
                board[x][y] = c;
            }
        }
    };
  • 相关阅读:
    buf.readUInt8()
    buf.readUIntBE()
    buf.readInt32BE()
    buf.readInt16BE()
    buf.readInt8()
    buf.readDoubleBE()
    buf.readFloatBE()
    buf.readIntBE()
    POJ
    【C#】C#托付和事件的实例解说
  • 原文地址:https://www.cnblogs.com/heyn1/p/11051413.html
Copyright © 2011-2022 走看看